From 75863e71819bed31949dcc169624f4e76c5817b5 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 22 Jul 2023 21:03:56 +1000 Subject: [PATCH 1/4] feat(ui): logging cleanup - simplify access to app logger - spruce up and make consistent log format - improve messaging --- invokeai/frontend/web/package.json | 1 + .../frontend/web/src/app/components/App.tsx | 12 +- .../frontend/web/src/app/logging/logger.ts | 46 ++++++ .../frontend/web/src/app/logging/useLogger.ts | 55 ++------ .../middleware/listenerMiddleware/index.ts | 20 +-- .../addCommitStagingAreaImageListener.ts | 17 +-- .../listeners/boardIdSelected.ts | 5 +- .../listeners/canvasCopiedToClipboard.ts | 7 +- .../listeners/canvasDownloadedAsImage.ts | 7 +- .../listeners/canvasMerged.ts | 7 +- .../listeners/canvasSavedToGallery.ts | 7 +- .../listeners/controlNetAutoProcess.ts | 14 +- .../listeners/controlNetImageProcessed.ts | 11 +- .../listeners/imageAddedToBoard.ts | 13 +- .../listeners/imageDeleted.ts | 17 ++- .../listeners/imageDropped.ts | 11 +- .../listeners/imageRemovedFromBoard.ts | 20 +-- .../listeners/imageToDeleteSelected.ts | 5 +- .../listeners/imageUpdated.ts | 34 ----- .../listeners/imageUploaded.ts | 10 +- .../listeners/modelSelected.ts | 8 +- .../listeners/modelsLoaded.ts | 39 +++++- .../listeners/receivedOpenAPISchema.ts | 21 +-- .../listeners/sessionCanceled.ts | 27 ++-- .../listeners/sessionCreated.ts | 23 +-- .../listeners/sessionInvoked.ts | 25 ++-- .../listeners/sessionReadyToInvoke.ts | 14 +- .../listeners/socketio/socketConnected.ts | 8 +- .../listeners/socketio/socketDisconnected.ts | 11 +- .../socketio/socketGeneratorProgress.ts | 11 +- .../socketGraphExecutionStateComplete.ts | 10 +- .../socketio/socketInvocationComplete.ts | 11 +- .../socketio/socketInvocationError.ts | 11 +- .../socketio/socketInvocationStarted.ts | 14 +- .../listeners/socketio/socketModelLoad.ts | 58 ++++++++ .../socketio/socketModelLoadCompleted.ts | 28 ---- .../socketio/socketModelLoadStarted.ts | 28 ---- .../listeners/socketio/socketSubscribed.ts | 12 +- .../listeners/socketio/socketUnsubscribed.ts | 12 +- .../listeners/stagingAreaImageSaved.ts | 5 +- .../listeners/upscaleRequested.ts | 3 - .../listeners/userInvokedCanvas.ts | 13 +- .../listeners/userInvokedImageToImage.ts | 16 +-- .../listeners/userInvokedNodes.ts | 16 +-- .../listeners/userInvokedTextToImage.ts | 16 +-- .../frontend/web/src/common/util/serialize.ts | 4 + .../src/features/canvas/util/getCanvasData.ts | 12 +- .../util/graphBuilders/buildCanvasGraph.ts | 3 - .../buildCanvasImageToImageGraph.ts | 7 +- .../graphBuilders/buildCanvasInpaintGraph.ts | 7 +- .../buildCanvasTextToImageGraph.ts | 7 +- .../buildLinearImageToImageGraph.ts | 9 +- .../buildLinearTextToImageGraph.ts | 7 +- .../util/modelIdToControlNetModelParam.ts | 7 +- .../util/modelIdToLoRAModelParam.ts | 8 +- .../util/modelIdToMainModelParam.ts | 7 +- .../parameters/util/modelIdToVAEModelParam.ts | 7 +- .../SettingsModal/SettingsModal.tsx | 2 +- .../src/features/system/store/systemSlice.ts | 2 +- .../web/src/services/api/thunks/schema.ts | 7 +- .../web/src/services/api/thunks/session.ts | 9 +- .../web/src/services/events/actions.ts | 131 ++++++++---------- .../web/src/services/events/middleware.ts | 17 +-- .../services/events/util/setEventListeners.ts | 36 ++--- invokeai/frontend/web/yarn.lock | 5 + 65 files changed, 480 insertions(+), 573 deletions(-) create mode 100644 invokeai/frontend/web/src/app/logging/logger.ts delete mode 100644 invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUpdated.ts create mode 100644 invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts delete mode 100644 invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadCompleted.ts delete mode 100644 invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadStarted.ts create mode 100644 invokeai/frontend/web/src/common/util/serialize.ts diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 81d6b0c7c7..c58e7bdc97 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -69,6 +69,7 @@ "@mantine/core": "^6.0.14", "@mantine/form": "^6.0.15", "@mantine/hooks": "^6.0.14", + "@nanostores/react": "^0.7.1", "@reduxjs/toolkit": "^1.9.5", "@roarr/browser-log-writer": "^1.1.5", "chakra-ui-contextmenu": "^1.0.5", diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 092f1b0f89..963d285f72 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -14,6 +14,7 @@ import FloatingParametersPanelButtons from 'features/ui/components/FloatingParam import InvokeTabs from 'features/ui/components/InvokeTabs'; import ParametersDrawer from 'features/ui/components/ParametersDrawer'; import i18n from 'i18n'; +import { size } from 'lodash-es'; import { ReactNode, memo, useEffect } from 'react'; import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal'; import GlobalHotkeys from './GlobalHotkeys'; @@ -29,8 +30,7 @@ interface Props { const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { const language = useAppSelector(languageSelector); - const log = useLogger(); - + const logger = useLogger(); const dispatch = useAppDispatch(); useEffect(() => { @@ -38,9 +38,11 @@ const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { }, [language]); useEffect(() => { - log.info({ namespace: 'App', data: config }, 'Received config'); - dispatch(configChanged(config)); - }, [dispatch, config, log]); + if (size(config)) { + logger.info({ namespace: 'App', config }, 'Received config'); + dispatch(configChanged(config)); + } + }, [dispatch, config, logger]); useEffect(() => { dispatch(appStarted()); diff --git a/invokeai/frontend/web/src/app/logging/logger.ts b/invokeai/frontend/web/src/app/logging/logger.ts new file mode 100644 index 0000000000..ef27c98d1f --- /dev/null +++ b/invokeai/frontend/web/src/app/logging/logger.ts @@ -0,0 +1,46 @@ +import { createLogWriter } from '@roarr/browser-log-writer'; +import { atom } from 'nanostores'; +import { Logger, ROARR, Roarr } from 'roarr'; + +ROARR.write = createLogWriter(); + +export const BASE_CONTEXT = {}; +export const log = Roarr.child(BASE_CONTEXT); + +export const $logger = atom(Roarr.child(BASE_CONTEXT)); + +type LoggerNamespace = + | 'images' + | 'models' + | 'config' + | 'canvas' + | 'txt2img' + | 'img2img' + | 'nodes' + | 'system' + | 'socketio' + | 'session'; + +export const logger = (namespace: LoggerNamespace) => + $logger.get().child({ namespace }); + +export const VALID_LOG_LEVELS = [ + 'trace', + 'debug', + 'info', + 'warn', + 'error', + 'fatal', +] as const; + +export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number]; + +// Translate human-readable log levels to numbers, used for log filtering +export const LOG_LEVEL_MAP: Record = { + trace: 10, + debug: 20, + info: 30, + warn: 40, + error: 50, + fatal: 60, +}; diff --git a/invokeai/frontend/web/src/app/logging/useLogger.ts b/invokeai/frontend/web/src/app/logging/useLogger.ts index c69b13dc72..13c62edcd3 100644 --- a/invokeai/frontend/web/src/app/logging/useLogger.ts +++ b/invokeai/frontend/web/src/app/logging/useLogger.ts @@ -1,48 +1,19 @@ +import { useStore } from '@nanostores/react'; import { createSelector } from '@reduxjs/toolkit'; +import { createLogWriter } from '@roarr/browser-log-writer'; import { useAppSelector } from 'app/store/storeHooks'; import { systemSelector } from 'features/system/store/systemSelectors'; import { isEqual } from 'lodash-es'; import { useEffect } from 'react'; -import { LogLevelName, ROARR, Roarr } from 'roarr'; -import { createLogWriter } from '@roarr/browser-log-writer'; - -// Base logging context includes only the package name -const baseContext = { package: '@invoke-ai/invoke-ai-ui' }; - -// Create browser log writer -ROARR.write = createLogWriter(); - -// Module-scoped logger - can be imported and used anywhere -export let log = Roarr.child(baseContext); - -// Translate human-readable log levels to numbers, used for log filtering -export const LOG_LEVEL_MAP: Record = { - trace: 10, - debug: 20, - info: 30, - warn: 40, - error: 50, - fatal: 60, -}; - -export const VALID_LOG_LEVELS = [ - 'trace', - 'debug', - 'info', - 'warn', - 'error', - 'fatal', -] as const; - -export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number]; +import { ROARR, Roarr } from 'roarr'; +import { $logger, BASE_CONTEXT, LOG_LEVEL_MAP } from './logger'; const selector = createSelector( systemSelector, (system) => { - const { app_version, consoleLogLevel, shouldLogToConsole } = system; + const { consoleLogLevel, shouldLogToConsole } = system; return { - version: app_version, consoleLogLevel, shouldLogToConsole, }; @@ -55,8 +26,7 @@ const selector = createSelector( ); export const useLogger = () => { - const { version, consoleLogLevel, shouldLogToConsole } = - useAppSelector(selector); + const { consoleLogLevel, shouldLogToConsole } = useAppSelector(selector); // The provided Roarr browser log writer uses localStorage to config logging to console useEffect(() => { @@ -79,16 +49,13 @@ export const useLogger = () => { // Update the module-scoped logger context as needed useEffect(() => { const newContext: Record = { - ...baseContext, + ...BASE_CONTEXT, }; - if (version) { - newContext.version = version; - } + $logger.set(Roarr.child(newContext)); + }, []); - log = Roarr.child(newContext); - }, [version]); + const logger = useStore($logger); - // Use the logger within components - no different than just importing it directly - return log; + return logger; }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts index 6c3a4508b4..04f0ce7a0b 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts @@ -8,10 +8,11 @@ import { import type { AppDispatch, RootState } from '../../store'; import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener'; +import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts'; import { addAppConfigReceivedListener } from './listeners/appConfigReceived'; import { addAppStartedListener } from './listeners/appStarted'; -import { addBoardIdSelectedListener } from './listeners/boardIdSelected'; import { addDeleteBoardAndImagesFulfilledListener } from './listeners/boardAndImagesDeleted'; +import { addBoardIdSelectedListener } from './listeners/boardIdSelected'; import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard'; import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage'; import { addCanvasMergedListener } from './listeners/canvasMerged'; @@ -34,10 +35,6 @@ import { addImageRemovedFromBoardRejectedListener, } from './listeners/imageRemovedFromBoard'; import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected'; -import { - addImageUpdatedFulfilledListener, - addImageUpdatedRejectedListener, -} from './listeners/imageUpdated'; import { addImageUploadedFulfilledListener, addImageUploadedRejectedListener, @@ -69,17 +66,15 @@ import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCo import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete'; import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError'; import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted'; +import { addModelLoadEventListener } from './listeners/socketio/socketModelLoad'; import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed'; import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed'; import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved'; +import { addUpscaleRequestedListener } from './listeners/upscaleRequested'; import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas'; import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage'; import { addUserInvokedNodesListener } from './listeners/userInvokedNodes'; import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage'; -import { addModelLoadStartedEventListener } from './listeners/socketio/socketModelLoadStarted'; -import { addModelLoadCompletedEventListener } from './listeners/socketio/socketModelLoadCompleted'; -import { addUpscaleRequestedListener } from './listeners/upscaleRequested'; -import { addFirstListImagesListener } from './listeners/addFirstListImagesListener.ts'; export const listenerMiddleware = createListenerMiddleware(); @@ -109,10 +104,6 @@ export type AppListenerEffect = ListenerEffect< addImageUploadedFulfilledListener(); addImageUploadedRejectedListener(); -// Image updated -addImageUpdatedFulfilledListener(); -addImageUpdatedRejectedListener(); - // Image selected addInitialImageSelectedListener(); @@ -161,8 +152,7 @@ addSocketConnectedListener(); addSocketDisconnectedListener(); addSocketSubscribedListener(); addSocketUnsubscribedListener(); -addModelLoadStartedEventListener(); -addModelLoadCompletedEventListener(); +addModelLoadEventListener(); // Session Created addSessionCreatedPendingListener(); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts index 322cc51fa7..d157fae7ed 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addCommitStagingAreaImageListener.ts @@ -1,14 +1,13 @@ -import { startAppListening } from '..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { commitStagingAreaImage } from 'features/canvas/store/canvasSlice'; import { sessionCanceled } from 'services/api/thunks/session'; - -const moduleLog = log.child({ namespace: 'canvas' }); +import { startAppListening } from '..'; export const addCommitStagingAreaImageListener = () => { startAppListening({ actionCreator: commitStagingAreaImage, effect: async (action, { dispatch, getState }) => { + const log = logger('canvas'); const state = getState(); const { sessionId: session_id, isProcessing } = state.system; const canvasSessionId = action.payload; @@ -19,17 +18,15 @@ export const addCommitStagingAreaImageListener = () => { } if (!canvasSessionId) { - moduleLog.debug('No canvas session, skipping cancel'); + log.debug('No canvas session, skipping cancel'); return; } if (canvasSessionId !== session_id) { - moduleLog.debug( + log.debug( { - data: { - canvasSessionId, - session_id, - }, + canvasSessionId, + session_id, }, 'Canvas session does not match global session, skipping cancel' ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts index b44f87a081..bf4dc7918c 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { isAnyOf } from '@reduxjs/toolkit'; import { ASSETS_CATEGORIES, IMAGE_CATEGORIES, @@ -8,9 +8,6 @@ import { } from 'features/gallery/store/gallerySlice'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -import { isAnyOf } from '@reduxjs/toolkit'; - -const moduleLog = log.child({ namespace: 'boards' }); export const addBoardIdSelectedListener = () => { startAppListening({ diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasCopiedToClipboard.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasCopiedToClipboard.ts index a7ddd8e917..9e66d1bdb8 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasCopiedToClipboard.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasCopiedToClipboard.ts @@ -1,16 +1,17 @@ import { canvasCopiedToClipboard } from 'features/canvas/store/actions'; import { startAppListening } from '..'; -import { log } from 'app/logging/useLogger'; +import { $logger } from 'app/logging/logger'; import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob'; import { addToast } from 'features/system/store/systemSlice'; import { copyBlobToClipboard } from 'features/canvas/util/copyBlobToClipboard'; -const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' }); - export const addCanvasCopiedToClipboardListener = () => { startAppListening({ actionCreator: canvasCopiedToClipboard, effect: async (action, { dispatch, getState }) => { + const moduleLog = $logger + .get() + .child({ namespace: 'canvasCopiedToClipboardListener' }); const state = getState(); const blob = await getBaseLayerBlob(state); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasDownloadedAsImage.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasDownloadedAsImage.ts index c97df09cff..b101d00541 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasDownloadedAsImage.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasDownloadedAsImage.ts @@ -1,16 +1,17 @@ import { canvasDownloadedAsImage } from 'features/canvas/store/actions'; import { startAppListening } from '..'; -import { log } from 'app/logging/useLogger'; +import { $logger } from 'app/logging/logger'; import { downloadBlob } from 'features/canvas/util/downloadBlob'; import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob'; import { addToast } from 'features/system/store/systemSlice'; -const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' }); - export const addCanvasDownloadedAsImageListener = () => { startAppListening({ actionCreator: canvasDownloadedAsImage, effect: async (action, { dispatch, getState }) => { + const moduleLog = $logger + .get() + .child({ namespace: 'canvasSavedToGalleryListener' }); const state = getState(); const blob = await getBaseLayerBlob(state); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts index 8a05c79a66..c55eb7bc2b 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { $logger } from 'app/logging/logger'; import { canvasMerged } from 'features/canvas/store/actions'; import { setMergedCanvas } from 'features/canvas/store/canvasSlice'; import { getFullBaseLayerBlob } from 'features/canvas/util/getFullBaseLayerBlob'; @@ -7,12 +7,13 @@ import { addToast } from 'features/system/store/systemSlice'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'canvasCopiedToClipboardListener' }); - export const addCanvasMergedListener = () => { startAppListening({ actionCreator: canvasMerged, effect: async (action, { dispatch, getState, take }) => { + const moduleLog = $logger + .get() + .child({ namespace: 'canvasCopiedToClipboardListener' }); const blob = await getFullBaseLayerBlob(); if (!blob) { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts index b8fa5ad00e..8e7dc0c8ea 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts @@ -1,22 +1,21 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { canvasSavedToGallery } from 'features/canvas/store/actions'; import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob'; import { addToast } from 'features/system/store/systemSlice'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' }); - export const addCanvasSavedToGalleryListener = () => { startAppListening({ actionCreator: canvasSavedToGallery, effect: async (action, { dispatch, getState, take }) => { + const log = logger('canvas'); const state = getState(); const blob = await getBaseLayerBlob(state); if (!blob) { - moduleLog.error('Problem getting base layer blob'); + log.error('Problem getting base layer blob'); dispatch( addToast({ title: 'Problem Saving Canvas', diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts index a923bd0b60..3aa01d54cb 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts @@ -1,6 +1,6 @@ import { AnyListenerPredicate } from '@reduxjs/toolkit'; -import { startAppListening } from '..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; +import { RootState } from 'app/store/store'; import { controlNetImageProcessed } from 'features/controlNet/store/actions'; import { controlNetAutoConfigToggled, @@ -9,9 +9,7 @@ import { controlNetProcessorParamsChanged, controlNetProcessorTypeChanged, } from 'features/controlNet/store/controlNetSlice'; -import { RootState } from 'app/store/store'; - -const moduleLog = log.child({ namespace: 'controlNet' }); +import { startAppListening } from '..'; const predicate: AnyListenerPredicate = ( action, @@ -68,14 +66,12 @@ export const addControlNetAutoProcessListener = () => { action, { dispatch, getState, cancelActiveListeners, delay } ) => { + const log = logger('session'); const { controlNetId } = action.payload; // Cancel any in-progress instances of this listener cancelActiveListeners(); - moduleLog.trace( - { data: action.payload }, - 'ControlNet auto-process triggered' - ); + log.trace('ControlNet auto-process triggered'); // Delay before starting actual work await delay(300); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts index 8d369a021f..830585154c 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { $logger, logger } from 'app/logging/logger'; import { controlNetImageProcessed } from 'features/controlNet/store/actions'; import { controlNetProcessedImageChanged } from 'features/controlNet/store/controlNetSlice'; import { sessionReadyToInvoke } from 'features/system/store/actions'; @@ -9,8 +9,6 @@ import { Graph, ImageDTO } from 'services/api/types'; import { socketInvocationComplete } from 'services/events/actions'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'controlNet' }); - export const addControlNetImageProcessedListener = () => { startAppListening({ actionCreator: controlNetImageProcessed, @@ -18,11 +16,12 @@ export const addControlNetImageProcessedListener = () => { action, { dispatch, getState, take, unsubscribe, subscribe } ) => { + const log = logger('session'); const { controlNetId } = action.payload; const controlNet = getState().controlNet.controlNets[controlNetId]; if (!controlNet.controlImage) { - moduleLog.error('Unable to process ControlNet image'); + log.error('Unable to process ControlNet image'); return; } @@ -70,8 +69,8 @@ export const addControlNetImageProcessedListener = () => { const processedControlImage = payload as ImageDTO; - moduleLog.debug( - { data: { arg: action.payload, processedControlImage } }, + log.debug( + { controlNetId: action.payload, processedControlImage }, 'ControlNet image processed' ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts index 6e1c34a04d..eab627b3f4 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts @@ -1,18 +1,17 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'boards' }); - export const addImageAddedToBoardFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled, effect: (action, { getState, dispatch }) => { + const log = logger('images'); const { board_id, imageDTO } = action.meta.arg.originalArgs; // TODO: update listImages cache for this board - moduleLog.debug({ data: { board_id, imageDTO } }, 'Image added to board'); + log.debug({ board_id, imageDTO }, 'Image added to board'); }, }); }; @@ -21,12 +20,10 @@ export const addImageAddedToBoardRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.addImageToBoard.matchRejected, effect: (action, { getState, dispatch }) => { + const log = logger('images'); const { board_id, imageDTO } = action.meta.arg.originalArgs; - moduleLog.debug( - { data: { board_id, imageDTO } }, - 'Problem adding image to board' - ); + log.debug({ board_id, imageDTO }, 'Problem adding image to board'); }, }); }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts index f179530045..716b31768c 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors'; @@ -14,8 +14,6 @@ import { api } from 'services/api'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'image' }); - /** * Called when the user requests an image deletion */ @@ -23,6 +21,7 @@ export const addRequestedImageDeletionListener = () => { startAppListening({ actionCreator: imageDeletionConfirmed, effect: async (action, { dispatch, getState, condition }) => { + const log = logger('images'); const { imageDTO, imageUsage } = action.payload; dispatch(isModalOpenChanged(false)); @@ -108,6 +107,7 @@ export const addImageDeletedPendingListener = () => { startAppListening({ matcher: imagesApi.endpoints.deleteImage.matchPending, effect: (action, { dispatch, getState }) => { + const log = logger('images'); // }, }); @@ -120,10 +120,8 @@ export const addImageDeletedFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.deleteImage.matchFulfilled, effect: (action, { dispatch, getState }) => { - moduleLog.debug( - { data: { image: action.meta.arg.originalArgs } }, - 'Image deleted' - ); + const log = logger('images'); + log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Image deleted'); }, }); }; @@ -135,8 +133,9 @@ export const addImageDeletedRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.deleteImage.matchRejected, effect: (action, { dispatch, getState }) => { - moduleLog.debug( - { data: { image: action.meta.arg.originalArgs } }, + const log = logger('images'); + log.debug( + { imageDTO: action.meta.arg.originalArgs }, 'Unable to delete image' ); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts index a7c8306c64..296bd0b953 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts @@ -3,7 +3,7 @@ import { TypesafeDraggableData, TypesafeDroppableData, } from 'app/components/ImageDnd/typesafeDnd'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice'; import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice'; import { @@ -15,8 +15,6 @@ import { initialImageChanged } from 'features/parameters/store/generationSlice'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '../'; -const moduleLog = log.child({ namespace: 'dnd' }); - export const dndDropped = createAction<{ overData: TypesafeDroppableData; activeData: TypesafeDraggableData; @@ -26,13 +24,10 @@ export const addImageDroppedListener = () => { startAppListening({ actionCreator: dndDropped, effect: async (action, { dispatch, getState, take }) => { + const log = logger('images'); const { activeData, overData } = action.payload; - const state = getState(); - moduleLog.debug( - { data: { activeData, overData } }, - 'Image or selection dropped' - ); + log.debug({ activeData, overData }, 'Image or selection dropped'); // set current image if ( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts index a9dd6eda3c..33c8dd5372 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts @@ -1,19 +1,15 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'boards' }); - export const addImageRemovedFromBoardFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled, effect: (action, { getState, dispatch }) => { - const { board_id, image_name } = action.meta.arg.originalArgs; + const log = logger('images'); + const imageDTO = action.meta.arg.originalArgs; - moduleLog.debug( - { data: { board_id, image_name } }, - 'Image added to board' - ); + log.debug({ imageDTO }, 'Image removed from board'); }, }); }; @@ -22,12 +18,10 @@ export const addImageRemovedFromBoardRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected, effect: (action, { getState, dispatch }) => { - const { board_id, image_name } = action.meta.arg.originalArgs; + const log = logger('images'); + const imageDTO = action.meta.arg.originalArgs; - moduleLog.debug( - { data: { board_id, image_name } }, - 'Problem adding image to board' - ); + log.debug({ imageDTO }, 'Problem removing image from board'); }, }); }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts index 531981126a..77ebd5c994 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts @@ -1,13 +1,10 @@ -import { startAppListening } from '..'; -import { log } from 'app/logging/useLogger'; import { imageDeletionConfirmed, imageToDeleteSelected, isModalOpenChanged, selectImageUsage, } from 'features/imageDeletion/store/imageDeletionSlice'; - -const moduleLog = log.child({ namespace: 'image' }); +import { startAppListening } from '..'; export const addImageToDeleteSelectedListener = () => { startAppListening({ diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUpdated.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUpdated.ts deleted file mode 100644 index 851b6be33f..0000000000 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUpdated.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { log } from 'app/logging/useLogger'; -import { imagesApi } from 'services/api/endpoints/images'; -import { startAppListening } from '..'; - -const moduleLog = log.child({ namespace: 'image' }); - -export const addImageUpdatedFulfilledListener = () => { - // startAppListening({ - // matcher: imagesApi.endpoints.updateImage.matchFulfilled, - // effect: (action, { dispatch, getState }) => { - // moduleLog.debug( - // { - // data: { - // oldImage: action.meta.arg.originalArgs, - // updatedImage: action.payload, - // }, - // }, - // 'Image updated' - // ); - // }, - // }); -}; - -export const addImageUpdatedRejectedListener = () => { - // startAppListening({ - // matcher: imagesApi.endpoints.updateImage.matchRejected, - // effect: (action, { dispatch }) => { - // moduleLog.debug( - // { data: action.meta.arg.originalArgs }, - // 'Image update failed' - // ); - // }, - // }); -}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts index 93519cca97..40c2209077 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts @@ -1,5 +1,5 @@ import { UseToastOptions } from '@chakra-ui/react'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice'; import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice'; import { imagesAddedToBatch } from 'features/gallery/store/gallerySlice'; @@ -10,8 +10,6 @@ import { boardsApi } from 'services/api/endpoints/boards'; import { startAppListening } from '..'; import { imagesApi } from '../../../../../services/api/endpoints/images'; -const moduleLog = log.child({ namespace: 'image' }); - const DEFAULT_UPLOADED_TOAST: UseToastOptions = { title: 'Image Uploaded', status: 'success', @@ -21,11 +19,12 @@ export const addImageUploadedFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.uploadImage.matchFulfilled, effect: (action, { dispatch, getState }) => { + const log = logger('images'); const imageDTO = action.payload; const state = getState(); const { selectedBoardId, autoAddBoardId } = state.gallery; - moduleLog.debug({ arg: '', imageDTO }, 'Image uploaded'); + log.debug({ imageDTO }, 'Image uploaded'); const { postUploadAction } = action.meta.arg.originalArgs; @@ -140,9 +139,10 @@ export const addImageUploadedRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.uploadImage.matchRejected, effect: (action, { dispatch }) => { + const log = logger('images'); const { file, postUploadAction, ...rest } = action.meta.arg.originalArgs; const sanitizedData = { arg: { ...rest, file: '' } }; - moduleLog.error({ data: sanitizedData }, 'Image upload failed'); + log.error({ ...sanitizedData }, 'Image upload failed'); dispatch( addToast({ title: 'Image Upload Failed', diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts index 05076960fb..6612963096 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts @@ -1,5 +1,5 @@ import { makeToast } from 'app/components/Toaster'; -import { log } from 'app/logging/useLogger'; +import { $logger, logger } from 'app/logging/logger'; import { loraRemoved } from 'features/lora/store/loraSlice'; import { modelSelected } from 'features/parameters/store/actions'; import { @@ -12,17 +12,17 @@ import { forEach } from 'lodash-es'; import { startAppListening } from '..'; import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice'; -const moduleLog = log.child({ module: 'models' }); - export const addModelSelectedListener = () => { startAppListening({ actionCreator: modelSelected, effect: (action, { getState, dispatch }) => { + const log = logger('models'); + const state = getState(); const result = zMainModel.safeParse(action.payload); if (!result.success) { - moduleLog.error( + log.error( { error: result.error.format() }, 'Failed to parse main model' ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts index 5e3caa7c99..131898695a 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { $logger, logger } from 'app/logging/logger'; import { loraRemoved } from 'features/lora/store/loraSlice'; import { modelChanged, @@ -13,13 +13,16 @@ import { modelsApi } from 'services/api/endpoints/models'; import { startAppListening } from '..'; import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice'; -const moduleLog = log.child({ module: 'models' }); - export const addModelsLoadedListener = () => { startAppListening({ matcher: modelsApi.endpoints.getMainModels.matchFulfilled, effect: async (action, { getState, dispatch }) => { // models loaded, we need to ensure the selected model is available and if not, select the first one + const log = logger('models'); + log.info( + { models: action.payload.entities }, + `Main models loaded (${action.payload.ids.length})` + ); const currentModel = getState().generation.model; @@ -46,7 +49,7 @@ export const addModelsLoadedListener = () => { const result = zMainModel.safeParse(firstModel); if (!result.success) { - moduleLog.error( + log.error( { error: result.error.format() }, 'Failed to parse main model' ); @@ -60,6 +63,11 @@ export const addModelsLoadedListener = () => { matcher: modelsApi.endpoints.getVaeModels.matchFulfilled, effect: async (action, { getState, dispatch }) => { // VAEs loaded, need to reset the VAE is it's no longer available + const log = logger('models'); + log.info( + { models: action.payload.entities }, + `VAEs loaded (${action.payload.ids.length})` + ); const currentVae = getState().generation.vae; @@ -91,7 +99,7 @@ export const addModelsLoadedListener = () => { const result = zVaeModel.safeParse(firstModel); if (!result.success) { - moduleLog.error( + log.error( { error: result.error.format() }, 'Failed to parse VAE model' ); @@ -105,6 +113,11 @@ export const addModelsLoadedListener = () => { matcher: modelsApi.endpoints.getLoRAModels.matchFulfilled, effect: async (action, { getState, dispatch }) => { // LoRA models loaded - need to remove missing LoRAs from state + const log = logger('models'); + log.info( + { models: action.payload.entities }, + `LoRAs loaded (${action.payload.ids.length})` + ); const loras = getState().lora.loras; @@ -128,6 +141,12 @@ export const addModelsLoadedListener = () => { matcher: modelsApi.endpoints.getControlNetModels.matchFulfilled, effect: async (action, { getState, dispatch }) => { // ControlNet models loaded - need to remove missing ControlNets from state + const log = logger('models'); + log.info( + { models: action.payload.entities }, + `ControlNet models loaded (${action.payload.ids.length})` + ); + const controlNets = getState().controlNet.controlNets; forEach(controlNets, (controlNet, controlNetId) => { @@ -146,4 +165,14 @@ export const addModelsLoadedListener = () => { }); }, }); + startAppListening({ + matcher: modelsApi.endpoints.getTextualInversionModels.matchFulfilled, + effect: async (action, { getState, dispatch }) => { + const log = logger('models'); + log.info( + { models: action.payload.entities }, + `Embeddings loaded (${action.payload.ids.length})` + ); + }, + }); }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts index 3cc3147b45..e9bf690a27 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts @@ -1,24 +1,24 @@ +import { logger } from 'app/logging/logger'; +import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice'; +import { parseSchema } from 'features/nodes/util/parseSchema'; +import { size } from 'lodash-es'; import { receivedOpenAPISchema } from 'services/api/thunks/schema'; import { startAppListening } from '..'; -import { log } from 'app/logging/useLogger'; -import { parseSchema } from 'features/nodes/util/parseSchema'; -import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice'; -import { size } from 'lodash-es'; - -const schemaLog = log.child({ namespace: 'schema' }); +import { parseify } from 'common/util/serialize'; export const addReceivedOpenAPISchemaListener = () => { startAppListening({ actionCreator: receivedOpenAPISchema.fulfilled, effect: (action, { dispatch, getState }) => { + const log = logger('system'); const schemaJSON = action.payload; - schemaLog.info({ data: { schemaJSON } }, 'Dereferenced OpenAPI schema'); + log.debug({ schemaJSON }, 'Dereferenced OpenAPI schema'); const nodeTemplates = parseSchema(schemaJSON); - schemaLog.info( - { data: { nodeTemplates } }, + log.debug( + { nodeTemplates: parseify(nodeTemplates) }, `Built ${size(nodeTemplates)} node templates` ); @@ -29,7 +29,8 @@ export const addReceivedOpenAPISchemaListener = () => { startAppListening({ actionCreator: receivedOpenAPISchema.rejected, effect: (action, { dispatch, getState }) => { - schemaLog.error('Problem dereferencing OpenAPI Schema'); + const log = logger('system'); + log.error('Problem dereferencing OpenAPI Schema'); }, }); }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts index 85e2627d88..2bc4ecad39 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts @@ -1,14 +1,13 @@ -import { log } from 'app/logging/useLogger'; -import { startAppListening } from '..'; -import { sessionCanceled } from 'services/api/thunks/session'; +import { logger } from 'app/logging/logger'; import { serializeError } from 'serialize-error'; - -const moduleLog = log.child({ namespace: 'session' }); +import { sessionCanceled } from 'services/api/thunks/session'; +import { startAppListening } from '..'; export const addSessionCanceledPendingListener = () => { startAppListening({ actionCreator: sessionCanceled.pending, effect: (action, { getState, dispatch }) => { + const log = logger('session'); // }, }); @@ -18,11 +17,9 @@ export const addSessionCanceledFulfilledListener = () => { startAppListening({ actionCreator: sessionCanceled.fulfilled, effect: (action, { getState, dispatch }) => { + const log = logger('session'); const { session_id } = action.meta.arg; - moduleLog.debug( - { data: { session_id } }, - `Session canceled (${session_id})` - ); + log.debug({ session_id }, `Session canceled (${session_id})`); }, }); }; @@ -31,14 +28,14 @@ export const addSessionCanceledRejectedListener = () => { startAppListening({ actionCreator: sessionCanceled.rejected, effect: (action, { getState, dispatch }) => { + const log = logger('session'); + const { session_id } = action.meta.arg; if (action.payload) { - const { arg, error } = action.payload; - moduleLog.error( + const { error } = action.payload; + log.error( { - data: { - arg, - error: serializeError(error), - }, + session_id, + error: serializeError(error), }, `Problem canceling session` ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts index 9ae7105378..eeaf725818 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts @@ -1,14 +1,14 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; +import { parseify } from 'common/util/serialize'; import { serializeError } from 'serialize-error'; import { sessionCreated } from 'services/api/thunks/session'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'session' }); - export const addSessionCreatedPendingListener = () => { startAppListening({ actionCreator: sessionCreated.pending, effect: (action, { getState, dispatch }) => { + const log = logger('session'); // }, }); @@ -18,8 +18,12 @@ export const addSessionCreatedFulfilledListener = () => { startAppListening({ actionCreator: sessionCreated.fulfilled, effect: (action, { getState, dispatch }) => { + const log = logger('session'); const session = action.payload; - moduleLog.debug({ data: { session } }, `Session created (${session.id})`); + log.debug( + { session: parseify(session) }, + `Session created (${session.id})` + ); }, }); }; @@ -28,16 +32,13 @@ export const addSessionCreatedRejectedListener = () => { startAppListening({ actionCreator: sessionCreated.rejected, effect: (action, { getState, dispatch }) => { + const log = logger('session'); if (action.payload) { const { arg, error } = action.payload; + const graph = parseify(action.meta.arg); const stringifiedError = JSON.stringify(error); - moduleLog.error( - { - data: { - arg, - error: serializeError(error), - }, - }, + log.error( + { graph, error: serializeError(error) }, `Problem creating session: ${stringifiedError}` ); } diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts index 7fc2e07dcd..1c73f17444 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts @@ -1,14 +1,13 @@ -import { log } from 'app/logging/useLogger'; -import { startAppListening } from '..'; -import { sessionInvoked } from 'services/api/thunks/session'; +import { logger } from 'app/logging/logger'; import { serializeError } from 'serialize-error'; - -const moduleLog = log.child({ namespace: 'session' }); +import { sessionInvoked } from 'services/api/thunks/session'; +import { startAppListening } from '..'; export const addSessionInvokedPendingListener = () => { startAppListening({ actionCreator: sessionInvoked.pending, effect: (action, { getState, dispatch }) => { + const log = logger('session'); // }, }); @@ -18,11 +17,9 @@ export const addSessionInvokedFulfilledListener = () => { startAppListening({ actionCreator: sessionInvoked.fulfilled, effect: (action, { getState, dispatch }) => { + const log = logger('session'); const { session_id } = action.meta.arg; - moduleLog.debug( - { data: { session_id } }, - `Session invoked (${session_id})` - ); + log.debug({ session_id }, `Session invoked (${session_id})`); }, }); }; @@ -31,15 +28,15 @@ export const addSessionInvokedRejectedListener = () => { startAppListening({ actionCreator: sessionInvoked.rejected, effect: (action, { getState, dispatch }) => { + const log = logger('session'); + const { session_id } = action.meta.arg; if (action.payload) { const { arg, error } = action.payload; const stringifiedError = JSON.stringify(error); - moduleLog.error( + log.error( { - data: { - arg, - error: serializeError(error), - }, + session_id, + error: serializeError(error), }, `Problem invoking session: ${stringifiedError}` ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionReadyToInvoke.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionReadyToInvoke.ts index cc77403709..0267eb629b 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionReadyToInvoke.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionReadyToInvoke.ts @@ -1,20 +1,16 @@ -import { startAppListening } from '..'; -import { sessionInvoked } from 'services/api/thunks/session'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { sessionReadyToInvoke } from 'features/system/store/actions'; - -const moduleLog = log.child({ namespace: 'session' }); +import { sessionInvoked } from 'services/api/thunks/session'; +import { startAppListening } from '..'; export const addSessionReadyToInvokeListener = () => { startAppListening({ actionCreator: sessionReadyToInvoke, effect: (action, { getState, dispatch }) => { + const log = logger('session'); const { sessionId: session_id } = getState().system; if (session_id) { - moduleLog.debug( - { session_id }, - `Session ready to invoke (${session_id})})` - ); + log.debug({ session_id }, `Session ready to invoke (${session_id})})`); dispatch(sessionInvoked({ session_id })); } }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts index f01c3911da..ae0f049ae7 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts @@ -1,18 +1,16 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { modelsApi } from 'services/api/endpoints/models'; import { receivedOpenAPISchema } from 'services/api/thunks/schema'; import { appSocketConnected, socketConnected } from 'services/events/actions'; import { startAppListening } from '../..'; -const moduleLog = log.child({ namespace: 'socketio' }); - export const addSocketConnectedEventListener = () => { startAppListening({ actionCreator: socketConnected, effect: (action, { dispatch, getState }) => { - const { timestamp } = action.payload; + const log = logger('socketio'); - moduleLog.debug({ timestamp }, 'Connected'); + log.debug('Connected'); const { nodes, config } = getState(); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts index d5e8914cef..cce2bbf52a 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts @@ -1,17 +1,16 @@ -import { startAppListening } from '../..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { - socketDisconnected, appSocketDisconnected, + socketDisconnected, } from 'services/events/actions'; - -const moduleLog = log.child({ namespace: 'socketio' }); +import { startAppListening } from '../..'; export const addSocketDisconnectedEventListener = () => { startAppListening({ actionCreator: socketDisconnected, effect: (action, { dispatch, getState }) => { - moduleLog.debug(action.payload, 'Disconnected'); + const log = logger('socketio'); + log.debug('Disconnected'); // pass along the socket event as an application action dispatch(appSocketDisconnected(action.payload)); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGeneratorProgress.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGeneratorProgress.ts index 756444d644..72fa317037 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGeneratorProgress.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGeneratorProgress.ts @@ -1,28 +1,27 @@ -import { startAppListening } from '../..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { appSocketGeneratorProgress, socketGeneratorProgress, } from 'services/events/actions'; - -const moduleLog = log.child({ namespace: 'socketio' }); +import { startAppListening } from '../..'; export const addGeneratorProgressEventListener = () => { startAppListening({ actionCreator: socketGeneratorProgress, effect: (action, { dispatch, getState }) => { + const log = logger('socketio'); if ( getState().system.canceledSession === action.payload.data.graph_execution_state_id ) { - moduleLog.trace( + log.trace( action.payload, 'Ignored generator progress for canceled session' ); return; } - moduleLog.trace( + log.trace( action.payload, `Generator progress (${action.payload.data.node.type})` ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts index 7297825e32..98a581ea1f 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts @@ -1,20 +1,16 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { appSocketGraphExecutionStateComplete, socketGraphExecutionStateComplete, } from 'services/events/actions'; import { startAppListening } from '../..'; -const moduleLog = log.child({ namespace: 'socketio' }); - export const addGraphExecutionStateCompleteEventListener = () => { startAppListening({ actionCreator: socketGraphExecutionStateComplete, effect: (action, { dispatch, getState }) => { - moduleLog.debug( - action.payload, - `Session invocation complete (${action.payload.data.graph_execution_state_id})` - ); + const log = logger('socketio'); + log.debug(action.payload, 'Session complete'); // pass along the socket event as an application action dispatch(appSocketGraphExecutionStateComplete(action.payload)); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts index 83c1a9f716..1ba653dba3 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts @@ -1,4 +1,5 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; +import { parseify } from 'common/util/serialize'; import { addImageToStagingArea } from 'features/canvas/store/canvasSlice'; import { IMAGE_CATEGORIES, @@ -16,15 +17,16 @@ import { } from 'services/events/actions'; import { startAppListening } from '../..'; -const moduleLog = log.child({ namespace: 'socketio' }); const nodeDenylist = ['dataURL_image']; export const addInvocationCompleteEventListener = () => { startAppListening({ actionCreator: socketInvocationComplete, effect: async (action, { dispatch, getState, take }) => { - moduleLog.debug( - { data: action.payload }, + const log = logger('socketio'); + const { data } = action.payload; + log.debug( + { data: parseify(data) }, `Invocation complete (${action.payload.data.node.type})` ); const session_id = action.payload.data.graph_execution_state_id; @@ -36,7 +38,6 @@ export const addInvocationCompleteEventListener = () => { dispatch(sessionCanceled({ session_id })); } - const { data } = action.payload; const { result, node, graph_execution_state_id } = data; // This complete event has an associated image output diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts index f0dd656097..d40ff1e944 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts @@ -1,19 +1,18 @@ -import { startAppListening } from '../..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { appSocketInvocationError, socketInvocationError, } from 'services/events/actions'; - -const moduleLog = log.child({ namespace: 'socketio' }); +import { startAppListening } from '../..'; export const addInvocationErrorEventListener = () => { startAppListening({ actionCreator: socketInvocationError, effect: (action, { dispatch, getState }) => { - moduleLog.error( + const log = logger('socketio'); + log.error( action.payload, - `Invocation error (${action.payload.data.node.type}): ${action.payload.data.error}` + `Invocation error (${action.payload.data.node.type})` ); dispatch(appSocketInvocationError(action.payload)); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationStarted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationStarted.ts index 978be2fef5..15447e5350 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationStarted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationStarted.ts @@ -1,31 +1,27 @@ -import { startAppListening } from '../..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { appSocketInvocationStarted, socketInvocationStarted, } from 'services/events/actions'; - -const moduleLog = log.child({ namespace: 'socketio' }); +import { startAppListening } from '../..'; export const addInvocationStartedEventListener = () => { startAppListening({ actionCreator: socketInvocationStarted, effect: (action, { dispatch, getState }) => { + const log = logger('socketio'); if ( getState().system.canceledSession === action.payload.data.graph_execution_state_id ) { - moduleLog.trace( + log.trace( action.payload, 'Ignored invocation started for canceled session' ); return; } - moduleLog.debug( - action.payload, - `Invocation started (${action.payload.data.node.type})` - ); + log.debug(action.payload, 'Invocation started'); dispatch(appSocketInvocationStarted(action.payload)); }, }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts new file mode 100644 index 0000000000..f221485c1f --- /dev/null +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts @@ -0,0 +1,58 @@ +import { logger } from 'app/logging/logger'; +import { ModelType } from 'services/api/types'; +import { + appSocketModelLoadCompleted, + appSocketModelLoadStarted, + socketModelLoadCompleted, + socketModelLoadStarted, +} from 'services/events/actions'; +import { startAppListening } from '../..'; + +const MODEL_TYPES: Record = { + main: 'main', + vae: 'VAE', + lora: 'LoRA', + controlnet: 'ControlNet', + embedding: 'embedding', +}; + +export const addModelLoadEventListener = () => { + startAppListening({ + actionCreator: socketModelLoadStarted, + effect: (action, { dispatch, getState }) => { + const log = logger('socketio'); + const { base_model, model_name, model_type, submodel } = + action.payload.data; + + let message = `Model load started: ${base_model}/${model_type}/${model_name}`; + + if (submodel) { + message = message.concat(`/${submodel}`); + } + + log.debug(action.payload, message); + + // pass along the socket event as an application action + dispatch(appSocketModelLoadStarted(action.payload)); + }, + }); + + startAppListening({ + actionCreator: socketModelLoadCompleted, + effect: (action, { dispatch, getState }) => { + const log = logger('socketio'); + const { base_model, model_name, model_type, submodel } = + action.payload.data; + + let message = `Model load complete: ${base_model}/${model_type}/${model_name}`; + + if (submodel) { + message = message.concat(`/${submodel}`); + } + + log.debug(action.payload, message); + // pass along the socket event as an application action + dispatch(appSocketModelLoadCompleted(action.payload)); + }, + }); +}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadCompleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadCompleted.ts deleted file mode 100644 index bc533b9178..0000000000 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadCompleted.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { log } from 'app/logging/useLogger'; -import { - appSocketModelLoadCompleted, - socketModelLoadCompleted, -} from 'services/events/actions'; -import { startAppListening } from '../..'; - -const moduleLog = log.child({ namespace: 'socketio' }); - -export const addModelLoadCompletedEventListener = () => { - startAppListening({ - actionCreator: socketModelLoadCompleted, - effect: (action, { dispatch, getState }) => { - const { model_name, model_type, submodel } = action.payload.data; - - let modelString = `${model_type} model: ${model_name}`; - - if (submodel) { - modelString = modelString.concat(`, submodel: ${submodel}`); - } - - moduleLog.debug(action.payload, `Model load completed (${modelString})`); - - // pass along the socket event as an application action - dispatch(appSocketModelLoadCompleted(action.payload)); - }, - }); -}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadStarted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadStarted.ts deleted file mode 100644 index aa53a70cee..0000000000 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoadStarted.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { log } from 'app/logging/useLogger'; -import { - appSocketModelLoadStarted, - socketModelLoadStarted, -} from 'services/events/actions'; -import { startAppListening } from '../..'; - -const moduleLog = log.child({ namespace: 'socketio' }); - -export const addModelLoadStartedEventListener = () => { - startAppListening({ - actionCreator: socketModelLoadStarted, - effect: (action, { dispatch, getState }) => { - const { model_name, model_type, submodel } = action.payload.data; - - let modelString = `${model_type} model: ${model_name}`; - - if (submodel) { - modelString = modelString.concat(`, submodel: ${submodel}`); - } - - moduleLog.debug(action.payload, `Model load started (${modelString})`); - - // pass along the socket event as an application action - dispatch(appSocketModelLoadStarted(action.payload)); - }, - }); -}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts index 871222981d..c01d6e915f 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts @@ -1,17 +1,13 @@ -import { startAppListening } from '../..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { appSocketSubscribed, socketSubscribed } from 'services/events/actions'; - -const moduleLog = log.child({ namespace: 'socketio' }); +import { startAppListening } from '../..'; export const addSocketSubscribedEventListener = () => { startAppListening({ actionCreator: socketSubscribed, effect: (action, { dispatch, getState }) => { - moduleLog.debug( - action.payload, - `Subscribed (${action.payload.sessionId}))` - ); + const log = logger('socketio'); + log.debug(action.payload, 'Subscribed'); dispatch(appSocketSubscribed(action.payload)); }, }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts index ff85379907..d8baa2cf27 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts @@ -1,20 +1,16 @@ -import { startAppListening } from '../..'; -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { appSocketUnsubscribed, socketUnsubscribed, } from 'services/events/actions'; - -const moduleLog = log.child({ namespace: 'socketio' }); +import { startAppListening } from '../..'; export const addSocketUnsubscribedEventListener = () => { startAppListening({ actionCreator: socketUnsubscribed, effect: (action, { dispatch, getState }) => { - moduleLog.debug( - action.payload, - `Unsubscribed (${action.payload.sessionId})` - ); + const log = logger('socketio'); + log.debug(action.payload, 'Unsubscribed'); dispatch(appSocketUnsubscribed(action.payload)); }, }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts index 1d175e6e90..5aea377624 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts @@ -1,15 +1,14 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { stagingAreaImageSaved } from 'features/canvas/store/actions'; import { addToast } from 'features/system/store/systemSlice'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'canvas' }); - export const addStagingAreaImageSavedListener = () => { startAppListening({ actionCreator: stagingAreaImageSaved, effect: async (action, { dispatch, getState, take }) => { + const log = logger('canvas'); const { imageDTO } = action.payload; try { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts index 4b8ac59b88..df597a3b62 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts @@ -1,12 +1,9 @@ import { createAction } from '@reduxjs/toolkit'; -import { log } from 'app/logging/useLogger'; import { buildAdHocUpscaleGraph } from 'features/nodes/util/graphBuilders/buildAdHocUpscaleGraph'; import { sessionReadyToInvoke } from 'features/system/store/actions'; import { sessionCreated } from 'services/api/thunks/session'; import { startAppListening } from '..'; -const moduleLog = log.child({ namespace: 'upscale' }); - export const upscaleRequested = createAction<{ image_name: string }>( `upscale/upscaleRequested` ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts index 6cfe2a58fb..2ef62aed7b 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { userInvoked } from 'app/store/actions'; import openBase64ImageInTab from 'common/util/openBase64ImageInTab'; import { @@ -15,8 +15,7 @@ import { imagesApi } from 'services/api/endpoints/images'; import { sessionCreated } from 'services/api/thunks/session'; import { ImageDTO } from 'services/api/types'; import { startAppListening } from '..'; - -const moduleLog = log.child({ namespace: 'invoke' }); +import { parseify } from 'common/util/serialize'; /** * This listener is responsible invoking the canvas. This involves a number of steps: @@ -36,13 +35,15 @@ export const addUserInvokedCanvasListener = () => { predicate: (action): action is ReturnType => userInvoked.match(action) && action.payload === 'unifiedCanvas', effect: async (action, { getState, dispatch, take }) => { + const log = logger('session'); + const state = getState(); // Build canvas blobs const canvasBlobsAndImageData = await getCanvasData(state); if (!canvasBlobsAndImageData) { - moduleLog.error('Unable to create canvas data'); + log.error('Unable to create canvas data'); return; } @@ -64,7 +65,7 @@ export const addUserInvokedCanvasListener = () => { ]); } - moduleLog.debug(`Generation mode: ${generationMode}`); + log.debug(`Generation mode: ${generationMode}`); // Temp placeholders for the init and mask images let canvasInitImage: ImageDTO | undefined; @@ -105,7 +106,7 @@ export const addUserInvokedCanvasListener = () => { canvasMaskImage ); - moduleLog.debug({ graph }, `Canvas graph built`); + log.debug({ graph: parseify(graph) }, `Canvas graph built`); // currently this action is just listened to for logging dispatch(canvasGraphBuilt(graph)); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts index 202dd6f487..8101530eea 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedImageToImage.ts @@ -1,23 +1,23 @@ -import { startAppListening } from '..'; -import { sessionCreated } from 'services/api/thunks/session'; -import { log } from 'app/logging/useLogger'; -import { imageToImageGraphBuilt } from 'features/nodes/store/actions'; +import { logger } from 'app/logging/logger'; import { userInvoked } from 'app/store/actions'; -import { sessionReadyToInvoke } from 'features/system/store/actions'; +import { parseify } from 'common/util/serialize'; +import { imageToImageGraphBuilt } from 'features/nodes/store/actions'; import { buildLinearImageToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearImageToImageGraph'; - -const moduleLog = log.child({ namespace: 'invoke' }); +import { sessionReadyToInvoke } from 'features/system/store/actions'; +import { sessionCreated } from 'services/api/thunks/session'; +import { startAppListening } from '..'; export const addUserInvokedImageToImageListener = () => { startAppListening({ predicate: (action): action is ReturnType => userInvoked.match(action) && action.payload === 'img2img', effect: async (action, { getState, dispatch, take }) => { + const log = logger('session'); const state = getState(); const graph = buildLinearImageToImageGraph(state); dispatch(imageToImageGraphBuilt(graph)); - moduleLog.debug({ data: graph }, 'Image to Image graph built'); + log.debug({ graph: parseify(graph) }, 'Image to Image graph built'); dispatch(sessionCreated({ graph })); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts index 9fb0009b70..0c298cbb24 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedNodes.ts @@ -1,23 +1,23 @@ -import { startAppListening } from '..'; -import { sessionCreated } from 'services/api/thunks/session'; -import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph'; -import { log } from 'app/logging/useLogger'; -import { nodesGraphBuilt } from 'features/nodes/store/actions'; +import { logger } from 'app/logging/logger'; import { userInvoked } from 'app/store/actions'; +import { parseify } from 'common/util/serialize'; +import { nodesGraphBuilt } from 'features/nodes/store/actions'; +import { buildNodesGraph } from 'features/nodes/util/graphBuilders/buildNodesGraph'; import { sessionReadyToInvoke } from 'features/system/store/actions'; - -const moduleLog = log.child({ namespace: 'invoke' }); +import { sessionCreated } from 'services/api/thunks/session'; +import { startAppListening } from '..'; export const addUserInvokedNodesListener = () => { startAppListening({ predicate: (action): action is ReturnType => userInvoked.match(action) && action.payload === 'nodes', effect: async (action, { getState, dispatch, take }) => { + const log = logger('session'); const state = getState(); const graph = buildNodesGraph(state); dispatch(nodesGraphBuilt(graph)); - moduleLog.debug({ data: graph }, 'Nodes graph built'); + log.debug({ graph: parseify(graph) }, 'Nodes graph built'); dispatch(sessionCreated({ graph })); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts index b024e94d9c..a9e9fe1ad8 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedTextToImage.ts @@ -1,25 +1,25 @@ -import { startAppListening } from '..'; -import { sessionCreated } from 'services/api/thunks/session'; -import { log } from 'app/logging/useLogger'; -import { textToImageGraphBuilt } from 'features/nodes/store/actions'; +import { logger } from 'app/logging/logger'; import { userInvoked } from 'app/store/actions'; -import { sessionReadyToInvoke } from 'features/system/store/actions'; +import { parseify } from 'common/util/serialize'; +import { textToImageGraphBuilt } from 'features/nodes/store/actions'; import { buildLinearTextToImageGraph } from 'features/nodes/util/graphBuilders/buildLinearTextToImageGraph'; - -const moduleLog = log.child({ namespace: 'invoke' }); +import { sessionReadyToInvoke } from 'features/system/store/actions'; +import { sessionCreated } from 'services/api/thunks/session'; +import { startAppListening } from '..'; export const addUserInvokedTextToImageListener = () => { startAppListening({ predicate: (action): action is ReturnType => userInvoked.match(action) && action.payload === 'txt2img', effect: async (action, { getState, dispatch, take }) => { + const log = logger('session'); const state = getState(); const graph = buildLinearTextToImageGraph(state); dispatch(textToImageGraphBuilt(graph)); - moduleLog.debug({ data: graph }, 'Text to Image graph built'); + log.debug({ graph: parseify(graph) }, 'Text to Image graph built'); dispatch(sessionCreated({ graph })); diff --git a/invokeai/frontend/web/src/common/util/serialize.ts b/invokeai/frontend/web/src/common/util/serialize.ts new file mode 100644 index 0000000000..a9352a8228 --- /dev/null +++ b/invokeai/frontend/web/src/common/util/serialize.ts @@ -0,0 +1,4 @@ +/** + * Serialize an object to JSON and back to a new object + */ +export const parseify = (obj: unknown) => JSON.parse(JSON.stringify(obj)); diff --git a/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts b/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts index d0190878e2..d37ee7b8d0 100644 --- a/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts +++ b/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts @@ -1,22 +1,22 @@ +import { logger } from 'app/logging/logger'; import { RootState } from 'app/store/store'; -import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider'; import { isCanvasMaskLine } from '../store/canvasTypes'; -import { log } from 'app/logging/useLogger'; import createMaskStage from './createMaskStage'; -import { konvaNodeToImageData } from './konvaNodeToImageData'; +import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider'; import { konvaNodeToBlob } from './konvaNodeToBlob'; - -const moduleLog = log.child({ namespace: 'getCanvasDataURLs' }); +import { konvaNodeToImageData } from './konvaNodeToImageData'; /** * Gets Blob and ImageData objects for the base and mask layers */ export const getCanvasData = async (state: RootState) => { + const log = logger('canvas'); + const canvasBaseLayer = getCanvasBaseLayer(); const canvasStage = getCanvasStage(); if (!canvasBaseLayer || !canvasStage) { - moduleLog.error('Unable to find canvas / stage'); + log.error('Unable to find canvas / stage'); return; } diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts index 5d6d7d141b..8a7716071f 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasGraph.ts @@ -1,4 +1,3 @@ -import { log } from 'app/logging/useLogger'; import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { ImageDTO } from 'services/api/types'; @@ -6,8 +5,6 @@ import { buildCanvasImageToImageGraph } from './buildCanvasImageToImageGraph'; import { buildCanvasInpaintGraph } from './buildCanvasInpaintGraph'; import { buildCanvasTextToImageGraph } from './buildCanvasTextToImageGraph'; -const moduleLog = log.child({ namespace: 'nodes' }); - export const buildCanvasGraph = ( state: RootState, generationMode: 'txt2img' | 'img2img' | 'inpaint' | 'outpaint', diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts index fef44bd549..4ef3ff77d2 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { initialGenerationState } from 'features/parameters/store/generationSlice'; @@ -25,8 +25,6 @@ import { RESIZE, } from './constants'; -const moduleLog = log.child({ namespace: 'nodes' }); - /** * Builds the Canvas tab's Image to Image graph. */ @@ -34,6 +32,7 @@ export const buildCanvasImageToImageGraph = ( state: RootState, initialImage: ImageDTO ): NonNullableGraph => { + const log = logger('nodes'); const { positivePrompt, negativePrompt, @@ -53,7 +52,7 @@ export const buildCanvasImageToImageGraph = ( const { shouldAutoSave } = state.canvas; if (!model) { - moduleLog.error('No model found in state'); + log.error('No model found in state'); throw new Error('No model found in state'); } diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts index d2abff1028..fa6e20aaa4 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { @@ -21,8 +21,6 @@ import { RANGE_OF_SIZE, } from './constants'; -const moduleLog = log.child({ namespace: 'nodes' }); - /** * Builds the Canvas tab's Inpaint graph. */ @@ -31,6 +29,7 @@ export const buildCanvasInpaintGraph = ( canvasInitImage: ImageDTO, canvasMaskImage: ImageDTO ): NonNullableGraph => { + const log = logger('nodes'); const { positivePrompt, negativePrompt, @@ -53,7 +52,7 @@ export const buildCanvasInpaintGraph = ( } = state.generation; if (!model) { - moduleLog.error('No model found in state'); + log.error('No model found in state'); throw new Error('No model found in state'); } diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts index a5ebbde289..d0eabbc14b 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { initialGenerationState } from 'features/parameters/store/generationSlice'; @@ -18,14 +18,13 @@ import { TEXT_TO_LATENTS, } from './constants'; -const moduleLog = log.child({ namespace: 'nodes' }); - /** * Builds the Canvas tab's Text to Image graph. */ export const buildCanvasTextToImageGraph = ( state: RootState ): NonNullableGraph => { + const log = logger('nodes'); const { positivePrompt, negativePrompt, @@ -44,7 +43,7 @@ export const buildCanvasTextToImageGraph = ( const { shouldAutoSave } = state.canvas; if (!model) { - moduleLog.error('No model found in state'); + log.error('No model found in state'); throw new Error('No model found in state'); } diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts index 9d200c4574..f5f5e670c9 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { initialGenerationState } from 'features/parameters/store/generationSlice'; @@ -24,14 +24,13 @@ import { RESIZE, } from './constants'; -const moduleLog = log.child({ namespace: 'nodes' }); - /** * Builds the Image to Image tab graph. */ export const buildLinearImageToImageGraph = ( state: RootState ): NonNullableGraph => { + const log = logger('nodes'); const { positivePrompt, negativePrompt, @@ -69,12 +68,12 @@ export const buildLinearImageToImageGraph = ( */ if (!initialImage) { - moduleLog.error('No initial image found in state'); + log.error('No initial image found in state'); throw new Error('No initial image found in state'); } if (!model) { - moduleLog.error('No model found in state'); + log.error('No model found in state'); throw new Error('No model found in state'); } diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts index 98af2a0a2f..c8529f95d3 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts @@ -1,4 +1,4 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { initialGenerationState } from 'features/parameters/store/generationSlice'; @@ -18,11 +18,10 @@ import { TEXT_TO_LATENTS, } from './constants'; -const moduleLog = log.child({ namespace: 'nodes' }); - export const buildLinearTextToImageGraph = ( state: RootState ): NonNullableGraph => { + const log = logger('nodes'); const { positivePrompt, negativePrompt, @@ -42,7 +41,7 @@ export const buildLinearTextToImageGraph = ( : initialGenerationState.shouldUseCpuNoise; if (!model) { - moduleLog.error('No model found in state'); + log.error('No model found in state'); throw new Error('No model found in state'); } diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts index c08bca0bbc..1da3325c09 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts @@ -1,12 +1,11 @@ -import { log } from 'app/logging/useLogger'; +import { logger } from 'app/logging/logger'; import { zControlNetModel } from 'features/parameters/types/parameterSchemas'; import { ControlNetModelField } from 'services/api/types'; -const moduleLog = log.child({ module: 'models' }); - export const modelIdToControlNetModelParam = ( controlNetModelId: string ): ControlNetModelField | undefined => { + const log = logger('models'); const [base_model, model_type, model_name] = controlNetModelId.split('/'); const result = zControlNetModel.safeParse({ @@ -15,7 +14,7 @@ export const modelIdToControlNetModelParam = ( }); if (!result.success) { - moduleLog.error( + log.error( { controlNetModelId, errors: result.error.format(), diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts index 206246c79e..ca8bd36e24 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts @@ -1,11 +1,11 @@ +import { logger } from 'app/logging/logger'; import { LoRAModelParam, zLoRAModel } from '../types/parameterSchemas'; -import { log } from 'app/logging/useLogger'; - -const moduleLog = log.child({ module: 'models' }); export const modelIdToLoRAModelParam = ( loraModelId: string ): LoRAModelParam | undefined => { + const log = logger('models'); + const [base_model, model_type, model_name] = loraModelId.split('/'); const result = zLoRAModel.safeParse({ @@ -14,7 +14,7 @@ export const modelIdToLoRAModelParam = ( }); if (!result.success) { - moduleLog.error( + log.error( { loraModelId, errors: result.error.format(), diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts index 70fb219bed..1468d9595e 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts @@ -1,14 +1,13 @@ +import { logger } from 'app/logging/logger'; import { MainModelParam, zMainModel, } from 'features/parameters/types/parameterSchemas'; -import { log } from 'app/logging/useLogger'; - -const moduleLog = log.child({ module: 'models' }); export const modelIdToMainModelParam = ( mainModelId: string ): MainModelParam | undefined => { + const log = logger('models'); const [base_model, model_type, model_name] = mainModelId.split('/'); const result = zMainModel.safeParse({ @@ -17,7 +16,7 @@ export const modelIdToMainModelParam = ( }); if (!result.success) { - moduleLog.error( + log.error( { mainModelId, errors: result.error.format(), diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts index eb57d07f0e..1d60ab1c84 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts @@ -1,11 +1,10 @@ +import { logger } from 'app/logging/logger'; import { VaeModelParam, zVaeModel } from '../types/parameterSchemas'; -import { log } from 'app/logging/useLogger'; - -const moduleLog = log.child({ module: 'models' }); export const modelIdToVAEModelParam = ( vaeModelId: string ): VaeModelParam | undefined => { + const log = logger('models'); const [base_model, model_type, model_name] = vaeModelId.split('/'); const result = zVaeModel.safeParse({ @@ -14,7 +13,7 @@ export const modelIdToVAEModelParam = ( }); if (!result.success) { - moduleLog.error( + log.error( { vaeModelId, errors: result.error.format(), diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 31dd6162ec..7df4c39cbb 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -12,7 +12,7 @@ import { useDisclosure, } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; -import { VALID_LOG_LEVELS } from 'app/logging/useLogger'; +import { VALID_LOG_LEVELS } from 'app/logging/logger'; import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 1f2b452151..12955092de 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -1,7 +1,7 @@ import { UseToastOptions } from '@chakra-ui/react'; import { PayloadAction, createSlice } from '@reduxjs/toolkit'; -import { InvokeLogLevel } from 'app/logging/useLogger'; +import { InvokeLogLevel } from 'app/logging/logger'; import { userInvoked } from 'app/store/actions'; import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice'; import { t } from 'i18next'; diff --git a/invokeai/frontend/web/src/services/api/thunks/schema.ts b/invokeai/frontend/web/src/services/api/thunks/schema.ts index 86d9f06eb4..9b5748ae41 100644 --- a/invokeai/frontend/web/src/services/api/thunks/schema.ts +++ b/invokeai/frontend/web/src/services/api/thunks/schema.ts @@ -1,7 +1,5 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; -import { log } from 'app/logging/useLogger'; - -const schemaLog = log.child({ namespace: 'schema' }); +import { logger } from 'app/logging/logger'; function getCircularReplacer() { const ancestors: Record[] = []; @@ -26,11 +24,12 @@ function getCircularReplacer() { export const receivedOpenAPISchema = createAsyncThunk( 'nodes/receivedOpenAPISchema', async (_, { dispatch, rejectWithValue }) => { + const log = logger('system'); try { const response = await fetch(`openapi.json`); const openAPISchema = await response.json(); - schemaLog.info({ openAPISchema }, 'Received OpenAPI schema'); + log.info({ openAPISchema }, 'Received OpenAPI schema'); const schemaJSON = JSON.parse( JSON.stringify(openAPISchema, getCircularReplacer()) diff --git a/invokeai/frontend/web/src/services/api/thunks/session.ts b/invokeai/frontend/web/src/services/api/thunks/session.ts index ac2b0a6c2a..1b4be92bc3 100644 --- a/invokeai/frontend/web/src/services/api/thunks/session.ts +++ b/invokeai/frontend/web/src/services/api/thunks/session.ts @@ -1,13 +1,10 @@ -import { createAppAsyncThunk } from 'app/store/storeUtils'; -import { log } from 'app/logging/useLogger'; -import { isObject } from 'lodash-es'; import { isAnyOf } from '@reduxjs/toolkit'; -import { paths } from 'services/api/schema'; +import { createAppAsyncThunk } from 'app/store/storeUtils'; +import { isObject } from 'lodash-es'; import { $client } from 'services/api/client'; +import { paths } from 'services/api/schema'; import { O } from 'ts-toolbelt'; -const sessionLog = log.child({ namespace: 'session' }); - type CreateSessionArg = { graph: NonNullable< paths['/api/v1/sessions/']['post']['requestBody'] diff --git a/invokeai/frontend/web/src/services/events/actions.ts b/invokeai/frontend/web/src/services/events/actions.ts index cb2d665748..b6316c5e95 100644 --- a/invokeai/frontend/web/src/services/events/actions.ts +++ b/invokeai/frontend/web/src/services/events/actions.ts @@ -9,11 +9,6 @@ import { ModelLoadStartedEvent, } from 'services/events/types'; -// Common socket action payload data -type BaseSocketPayload = { - timestamp: string; -}; - // Create actions for each socket // Middleware and redux can then respond to them as needed @@ -22,30 +17,24 @@ type BaseSocketPayload = { * * Do not use. Only for use in middleware. */ -export const socketConnected = createAction( - 'socket/socketConnected' -); +export const socketConnected = createAction('socket/socketConnected'); /** * App-level Socket.IO Connected */ -export const appSocketConnected = createAction( - 'socket/appSocketConnected' -); +export const appSocketConnected = createAction('socket/appSocketConnected'); /** * Socket.IO Disconnect * * Do not use. Only for use in middleware. */ -export const socketDisconnected = createAction( - 'socket/socketDisconnected' -); +export const socketDisconnected = createAction('socket/socketDisconnected'); /** * App-level Socket.IO Disconnected */ -export const appSocketDisconnected = createAction( +export const appSocketDisconnected = createAction( 'socket/appSocketDisconnected' ); @@ -54,145 +43,141 @@ export const appSocketDisconnected = createAction( * * Do not use. Only for use in middleware. */ -export const socketSubscribed = createAction< - BaseSocketPayload & { sessionId: string; boardId: string | undefined } ->('socket/socketSubscribed'); +export const socketSubscribed = createAction<{ + sessionId: string; +}>('socket/socketSubscribed'); /** * App-level Socket.IO Subscribed */ -export const appSocketSubscribed = createAction< - BaseSocketPayload & { sessionId: string; boardId: string | undefined } ->('socket/appSocketSubscribed'); +export const appSocketSubscribed = createAction<{ + sessionId: string; +}>('socket/appSocketSubscribed'); /** * Socket.IO Unsubscribed * * Do not use. Only for use in middleware. */ -export const socketUnsubscribed = createAction< - BaseSocketPayload & { sessionId: string } ->('socket/socketUnsubscribed'); +export const socketUnsubscribed = createAction<{ sessionId: string }>( + 'socket/socketUnsubscribed' +); /** * App-level Socket.IO Unsubscribed */ -export const appSocketUnsubscribed = createAction< - BaseSocketPayload & { sessionId: string } ->('socket/appSocketUnsubscribed'); +export const appSocketUnsubscribed = createAction<{ sessionId: string }>( + 'socket/appSocketUnsubscribed' +); /** * Socket.IO Invocation Started * * Do not use. Only for use in middleware. */ -export const socketInvocationStarted = createAction< - BaseSocketPayload & { data: InvocationStartedEvent } ->('socket/socketInvocationStarted'); +export const socketInvocationStarted = createAction<{ + data: InvocationStartedEvent; +}>('socket/socketInvocationStarted'); /** * App-level Socket.IO Invocation Started */ -export const appSocketInvocationStarted = createAction< - BaseSocketPayload & { data: InvocationStartedEvent } ->('socket/appSocketInvocationStarted'); +export const appSocketInvocationStarted = createAction<{ + data: InvocationStartedEvent; +}>('socket/appSocketInvocationStarted'); /** * Socket.IO Invocation Complete * * Do not use. Only for use in middleware. */ -export const socketInvocationComplete = createAction< - BaseSocketPayload & { - data: InvocationCompleteEvent; - } ->('socket/socketInvocationComplete'); +export const socketInvocationComplete = createAction<{ + data: InvocationCompleteEvent; +}>('socket/socketInvocationComplete'); /** * App-level Socket.IO Invocation Complete */ -export const appSocketInvocationComplete = createAction< - BaseSocketPayload & { - data: InvocationCompleteEvent; - } ->('socket/appSocketInvocationComplete'); +export const appSocketInvocationComplete = createAction<{ + data: InvocationCompleteEvent; +}>('socket/appSocketInvocationComplete'); /** * Socket.IO Invocation Error * * Do not use. Only for use in middleware. */ -export const socketInvocationError = createAction< - BaseSocketPayload & { data: InvocationErrorEvent } ->('socket/socketInvocationError'); +export const socketInvocationError = createAction<{ + data: InvocationErrorEvent; +}>('socket/socketInvocationError'); /** * App-level Socket.IO Invocation Error */ -export const appSocketInvocationError = createAction< - BaseSocketPayload & { data: InvocationErrorEvent } ->('socket/appSocketInvocationError'); +export const appSocketInvocationError = createAction<{ + data: InvocationErrorEvent; +}>('socket/appSocketInvocationError'); /** * Socket.IO Graph Execution State Complete * * Do not use. Only for use in middleware. */ -export const socketGraphExecutionStateComplete = createAction< - BaseSocketPayload & { data: GraphExecutionStateCompleteEvent } ->('socket/socketGraphExecutionStateComplete'); +export const socketGraphExecutionStateComplete = createAction<{ + data: GraphExecutionStateCompleteEvent; +}>('socket/socketGraphExecutionStateComplete'); /** * App-level Socket.IO Graph Execution State Complete */ -export const appSocketGraphExecutionStateComplete = createAction< - BaseSocketPayload & { data: GraphExecutionStateCompleteEvent } ->('socket/appSocketGraphExecutionStateComplete'); +export const appSocketGraphExecutionStateComplete = createAction<{ + data: GraphExecutionStateCompleteEvent; +}>('socket/appSocketGraphExecutionStateComplete'); /** * Socket.IO Generator Progress * * Do not use. Only for use in middleware. */ -export const socketGeneratorProgress = createAction< - BaseSocketPayload & { data: GeneratorProgressEvent } ->('socket/socketGeneratorProgress'); +export const socketGeneratorProgress = createAction<{ + data: GeneratorProgressEvent; +}>('socket/socketGeneratorProgress'); /** * App-level Socket.IO Generator Progress */ -export const appSocketGeneratorProgress = createAction< - BaseSocketPayload & { data: GeneratorProgressEvent } ->('socket/appSocketGeneratorProgress'); +export const appSocketGeneratorProgress = createAction<{ + data: GeneratorProgressEvent; +}>('socket/appSocketGeneratorProgress'); /** * Socket.IO Model Load Started * * Do not use. Only for use in middleware. */ -export const socketModelLoadStarted = createAction< - BaseSocketPayload & { data: ModelLoadStartedEvent } ->('socket/socketModelLoadStarted'); +export const socketModelLoadStarted = createAction<{ + data: ModelLoadStartedEvent; +}>('socket/socketModelLoadStarted'); /** * App-level Model Load Started */ -export const appSocketModelLoadStarted = createAction< - BaseSocketPayload & { data: ModelLoadStartedEvent } ->('socket/appSocketModelLoadStarted'); +export const appSocketModelLoadStarted = createAction<{ + data: ModelLoadStartedEvent; +}>('socket/appSocketModelLoadStarted'); /** * Socket.IO Model Load Started * * Do not use. Only for use in middleware. */ -export const socketModelLoadCompleted = createAction< - BaseSocketPayload & { data: ModelLoadCompletedEvent } ->('socket/socketModelLoadCompleted'); +export const socketModelLoadCompleted = createAction<{ + data: ModelLoadCompletedEvent; +}>('socket/socketModelLoadCompleted'); /** * App-level Model Load Completed */ -export const appSocketModelLoadCompleted = createAction< - BaseSocketPayload & { data: ModelLoadCompletedEvent } ->('socket/appSocketModelLoadCompleted'); +export const appSocketModelLoadCompleted = createAction<{ + data: ModelLoadCompletedEvent; +}>('socket/appSocketModelLoadCompleted'); diff --git a/invokeai/frontend/web/src/services/events/middleware.ts b/invokeai/frontend/web/src/services/events/middleware.ts index 665761a626..0c3b275274 100644 --- a/invokeai/frontend/web/src/services/events/middleware.ts +++ b/invokeai/frontend/web/src/services/events/middleware.ts @@ -1,20 +1,14 @@ import { Middleware, MiddlewareAPI } from '@reduxjs/toolkit'; -import { Socket, io } from 'socket.io-client'; - import { AppThunkDispatch, RootState } from 'app/store/store'; -import { getTimestamp } from 'common/util/getTimestamp'; +import { $authToken, $baseUrl } from 'services/api/client'; import { sessionCreated } from 'services/api/thunks/session'; import { ClientToServerEvents, ServerToClientEvents, } from 'services/events/types'; -import { socketSubscribed, socketUnsubscribed } from './actions'; -// import { OpenAPI } from 'services/api/types'; -import { log } from 'app/logging/useLogger'; -import { $authToken, $baseUrl } from 'services/api/client'; import { setEventListeners } from 'services/events/util/setEventListeners'; - -const socketioLog = log.child({ namespace: 'socketio' }); +import { Socket, io } from 'socket.io-client'; +import { socketSubscribed, socketUnsubscribed } from './actions'; export const socketMiddleware = () => { let areListenersSet = false; @@ -58,7 +52,7 @@ export const socketMiddleware = () => { // Set listeners for `connect` and `disconnect` events once // Must happen in middleware to get access to `dispatch` if (!areListenersSet) { - setEventListeners({ storeApi, socket, log: socketioLog }); + setEventListeners({ storeApi, socket }); areListenersSet = true; @@ -77,7 +71,6 @@ export const socketMiddleware = () => { dispatch( socketUnsubscribed({ sessionId: oldSessionId, - timestamp: getTimestamp(), }) ); } @@ -87,8 +80,6 @@ export const socketMiddleware = () => { dispatch( socketSubscribed({ sessionId: sessionId, - timestamp: getTimestamp(), - boardId: getState().gallery.selectedBoardId, }) ); } diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index 44d3301556..eaa5596e37 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -1,42 +1,40 @@ import { MiddlewareAPI } from '@reduxjs/toolkit'; +import { logger } from 'app/logging/logger'; import { AppDispatch, RootState } from 'app/store/store'; -import { getTimestamp } from 'common/util/getTimestamp'; import { Socket } from 'socket.io-client'; +import { makeToast } from '../../../app/components/Toaster'; +import { addToast } from '../../../features/system/store/systemSlice'; import { + socketConnected, + socketDisconnected, socketGeneratorProgress, socketGraphExecutionStateComplete, socketInvocationComplete, socketInvocationError, socketInvocationStarted, - socketConnected, - socketDisconnected, - socketSubscribed, - socketModelLoadStarted, socketModelLoadCompleted, + socketModelLoadStarted, + socketSubscribed, } from '../actions'; import { ClientToServerEvents, ServerToClientEvents } from '../types'; -import { Logger } from 'roarr'; -import { JsonObject } from 'roarr/dist/types'; -import { makeToast } from '../../../app/components/Toaster'; -import { addToast } from '../../../features/system/store/systemSlice'; type SetEventListenersArg = { socket: Socket; storeApi: MiddlewareAPI; - log: Logger; }; export const setEventListeners = (arg: SetEventListenersArg) => { - const { socket, storeApi, log } = arg; + const { socket, storeApi } = arg; const { dispatch, getState } = storeApi; /** * Connect */ socket.on('connect', () => { + const log = logger('socketio'); log.debug('Connected'); - dispatch(socketConnected({ timestamp: getTimestamp() })); + dispatch(socketConnected()); const { sessionId } = getState().system; @@ -45,8 +43,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => { dispatch( socketSubscribed({ sessionId, - timestamp: getTimestamp(), - boardId: getState().gallery.selectedBoardId, }) ); } @@ -73,28 +69,28 @@ export const setEventListeners = (arg: SetEventListenersArg) => { * Disconnect */ socket.on('disconnect', () => { - dispatch(socketDisconnected({ timestamp: getTimestamp() })); + dispatch(socketDisconnected()); }); /** * Invocation started */ socket.on('invocation_started', (data) => { - dispatch(socketInvocationStarted({ data, timestamp: getTimestamp() })); + dispatch(socketInvocationStarted({ data })); }); /** * Generator progress */ socket.on('generator_progress', (data) => { - dispatch(socketGeneratorProgress({ data, timestamp: getTimestamp() })); + dispatch(socketGeneratorProgress({ data })); }); /** * Invocation error */ socket.on('invocation_error', (data) => { - dispatch(socketInvocationError({ data, timestamp: getTimestamp() })); + dispatch(socketInvocationError({ data })); }); /** @@ -104,7 +100,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => { dispatch( socketInvocationComplete({ data, - timestamp: getTimestamp(), }) ); }); @@ -116,7 +111,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => { dispatch( socketGraphExecutionStateComplete({ data, - timestamp: getTimestamp(), }) ); }); @@ -128,7 +122,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => { dispatch( socketModelLoadStarted({ data, - timestamp: getTimestamp(), }) ); }); @@ -140,7 +133,6 @@ export const setEventListeners = (arg: SetEventListenersArg) => { dispatch( socketModelLoadCompleted({ data, - timestamp: getTimestamp(), }) ); }); diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index 6f110a1117..35208003d0 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -1511,6 +1511,11 @@ resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.14.2.tgz#c3ec604a0b54b9a9b87e9735dfc59e1a5da6a5fb" integrity sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug== +"@nanostores/react@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@nanostores/react/-/react-0.7.1.tgz#e0446f5cacc9fa53448c454f5d00ddb0f906a37a" + integrity sha512-EXQg9N4MdI4eJQz/AZLIx3hxQ6BuBmV4Q55bCd5YCSgEOAW7tGTsIZxpRXxvxLXzflNvHTBvfrDNY38TlSVBkQ== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" From 5468d9a9fc288a5958d7cb3ac36942662dc2dbbc Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 22 Jul 2023 21:38:50 +1000 Subject: [PATCH 2/4] fix(ui): resolve all typescript issues --- .../app/components/ImageDnd/DragPreview.tsx | 2 +- .../web/src/common/components/GuideIcon.tsx | 23 - .../src/common/components/GuidePopover.tsx | 49 -- .../web/src/common/components/IAIDndImage.tsx | 4 +- .../components/ImageMetadataOverlay.tsx | 21 +- .../src/common/hooks/useIsReadyToInvoke.ts | 25 +- .../src/common/util/getPromptAndNegative.ts | 31 -- .../web/src/common/util/promptToString.ts | 20 - .../web/src/common/util/seedWeightPairs.ts | 125 ++--- .../src/features/canvas/store/canvasTypes.ts | 3 - .../components/GalleryProgressImage.tsx | 73 --- .../components/ImageGrid/GalleryImageGrid.tsx | 2 + .../features/gallery/store/boardSelectors.ts | 23 - .../gallery/store/galleryPersistDenylist.ts | 7 - .../features/gallery/store/gallerySlice.ts | 5 +- .../lora/components/ParamLoraList.tsx | 8 +- .../nodes/components/ViewportControls.tsx | 21 +- .../Advanced/ParamAdvancedCollapse.tsx | 17 +- .../Seamless/ParamSeamlessToggle.tsx | 33 -- .../Parameters/Seed/ParamSeedCollapse.tsx | 48 -- .../Variations/ParamVariationCollapse.tsx | 84 ++-- .../Variations/ParamVariationWeights.tsx | 66 +-- .../features/system/store/systemSelectors.ts | 36 -- .../src/features/system/store/systemSlice.ts | 7 +- .../ui/components/tabs/Batch/BatchTab.tsx | 43 -- .../ImageToImageTabParameters.tsx | 7 +- .../AddModelsPanel/FoundModelsList.tsx | 6 +- .../AddModelsPanel/ScanAdvancedAddModels.tsx | 120 ++--- .../AddModelsPanel/SearchModelsOld.tsx | 430 ------------------ .../TextToImage/TextToImageTabParameters.tsx | 7 +- .../UnifiedCanvas/UnifiedCanvasParameters.tsx | 7 +- .../web/src/features/ui/store/uiSlice.ts | 7 +- .../api/models/HedImageprocessorInvocation.ts | 36 -- 33 files changed, 280 insertions(+), 1116 deletions(-) delete mode 100644 invokeai/frontend/web/src/common/components/GuideIcon.tsx delete mode 100644 invokeai/frontend/web/src/common/components/GuidePopover.tsx delete mode 100644 invokeai/frontend/web/src/common/util/getPromptAndNegative.ts delete mode 100644 invokeai/frontend/web/src/common/util/promptToString.ts delete mode 100644 invokeai/frontend/web/src/features/gallery/components/GalleryProgressImage.tsx delete mode 100644 invokeai/frontend/web/src/features/gallery/store/boardSelectors.ts delete mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/Seamless/ParamSeamlessToggle.tsx delete mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedCollapse.tsx delete mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx delete mode 100644 invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SearchModelsOld.tsx delete mode 100644 invokeai/frontend/web/src/services/api/models/HedImageprocessorInvocation.ts diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx index e8fa949e9a..82526900ad 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx @@ -27,7 +27,7 @@ const STYLES: ChakraProps['sx'] = { const DragPreview = (props: OverlayDragImageProps) => { if (!props.dragData) { - return; + return null; } if (props.dragData.payloadType === 'IMAGE_DTO') { diff --git a/invokeai/frontend/web/src/common/components/GuideIcon.tsx b/invokeai/frontend/web/src/common/components/GuideIcon.tsx deleted file mode 100644 index d8ac9dda0e..0000000000 --- a/invokeai/frontend/web/src/common/components/GuideIcon.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Box, forwardRef, Icon } from '@chakra-ui/react'; -import { Feature } from 'app/features'; -import { memo } from 'react'; -import { IconType } from 'react-icons'; -import { MdHelp } from 'react-icons/md'; -import GuidePopover from './GuidePopover'; - -type GuideIconProps = { - feature: Feature; - icon?: IconType; -}; - -const GuideIcon = forwardRef( - ({ feature, icon = MdHelp }: GuideIconProps, ref) => ( - - - - - - ) -); - -export default memo(GuideIcon); diff --git a/invokeai/frontend/web/src/common/components/GuidePopover.tsx b/invokeai/frontend/web/src/common/components/GuidePopover.tsx deleted file mode 100644 index 1cfb60a830..0000000000 --- a/invokeai/frontend/web/src/common/components/GuidePopover.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { - Box, - Popover, - PopoverArrow, - PopoverBody, - PopoverContent, - PopoverTrigger, -} from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { Feature, useFeatureHelpInfo } from 'app/features'; -import { useAppSelector } from 'app/store/storeHooks'; -import { systemSelector } from 'features/system/store/systemSelectors'; -import { SystemState } from 'features/system/store/systemSlice'; -import { memo, ReactElement } from 'react'; - -type GuideProps = { - children: ReactElement; - feature: Feature; -}; - -const guidePopoverSelector = createSelector( - systemSelector, - (system: SystemState) => system.shouldDisplayGuides -); - -const GuidePopover = ({ children, feature }: GuideProps) => { - const shouldDisplayGuides = useAppSelector(guidePopoverSelector); - const { text } = useFeatureHelpInfo(feature); - - if (!shouldDisplayGuides) return null; - - return ( - - - {children} - - e.preventDefault()} - cursor="initial" - > - - {text} - - - ); -}; - -export default memo(GuidePopover); diff --git a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx index cf01a93197..780447aba6 100644 --- a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx +++ b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx @@ -169,7 +169,9 @@ const IAIDndImage = (props: IAIDndImageProps) => { ...imageSx, }} /> - {withMetadataOverlay && } + {withMetadataOverlay && ( + + )} { - const model = useMemo(() => { - if (!isString(image.metadata?.model)) { - return; - } - - return image.metadata?.model; - }, [image.metadata]); - +const ImageMetadataOverlay = ({ imageDTO }: ImageMetadataOverlayProps) => { return ( { }} > - {image.width} × {image.height} + {imageDTO.width} × {imageDTO.height} - {model && ( - - {model} - - )} ); }; diff --git a/invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts b/invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts index 580206266d..384150be10 100644 --- a/invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts +++ b/invokeai/frontend/web/src/common/hooks/useIsReadyToInvoke.ts @@ -2,17 +2,16 @@ import { createSelector } from '@reduxjs/toolkit'; import { stateSelector } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { validateSeedWeights } from 'common/util/seedWeightPairs'; +// import { validateSeedWeights } from 'common/util/seedWeightPairs'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { modelsApi } from '../../services/api/endpoints/models'; import { forEach } from 'lodash-es'; +import { modelsApi } from '../../services/api/endpoints/models'; const readinessSelector = createSelector( [stateSelector, activeTabNameSelector], (state, activeTabName) => { const { generation, system } = state; - const { shouldGenerateVariations, seedWeights, initialImage, seed } = - generation; + const { initialImage } = generation; const { isProcessing, isConnected } = system; @@ -44,19 +43,19 @@ const readinessSelector = createSelector( reasonsWhyNotReady.push('System Disconnected'); } - // Cannot generate variations without valid seed weights - if ( - shouldGenerateVariations && - (!(validateSeedWeights(seedWeights) || seedWeights === '') || seed === -1) - ) { - isReady = false; - reasonsWhyNotReady.push('Seed-Weights badly formatted.'); - } + // // Cannot generate variations without valid seed weights + // if ( + // shouldGenerateVariations && + // (!(validateSeedWeights(seedWeights) || seedWeights === '') || seed === -1) + // ) { + // isReady = false; + // reasonsWhyNotReady.push('Seed-Weights badly formatted.'); + // } forEach(state.controlNet.controlNets, (controlNet, id) => { if (!controlNet.model) { isReady = false; - reasonsWhyNotReady.push('ControlNet ${id} has no model selected.'); + reasonsWhyNotReady.push(`ControlNet ${id} has no model selected.`); } }); diff --git a/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts b/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts deleted file mode 100644 index 4683d44428..0000000000 --- a/invokeai/frontend/web/src/common/util/getPromptAndNegative.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as InvokeAI from 'app/types/invokeai'; -import promptToString from './promptToString'; - -export function getPromptAndNegative(inputPrompt: InvokeAI.Prompt) { - let prompt: string = - typeof inputPrompt === 'string' ? inputPrompt : promptToString(inputPrompt); - - let negativePrompt = ''; - - // Matches all negative prompts, 1st capturing group is the prompt itself - const negativePromptRegExp = new RegExp(/\[([^\][]*)]/, 'gi'); - - // Grab the actual prompt matches (capturing group 1 is 1st index of match) - const negativePromptMatches = [...prompt.matchAll(negativePromptRegExp)].map( - (match) => match[1] - ); - - if (negativePromptMatches.length) { - // Build the negative prompt itself - negativePrompt = negativePromptMatches.join(' '); - - // Replace each match, including its surrounding brackets - // Remove each pair of empty brackets - // Trim whitespace - negativePromptMatches.forEach((match) => { - prompt = prompt.replace(`[${match}]`, '').replaceAll('[]', '').trim(); - }); - } - - return [prompt, negativePrompt]; -} diff --git a/invokeai/frontend/web/src/common/util/promptToString.ts b/invokeai/frontend/web/src/common/util/promptToString.ts deleted file mode 100644 index cb86af2988..0000000000 --- a/invokeai/frontend/web/src/common/util/promptToString.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as InvokeAI from 'app/types/invokeai'; - -const promptToString = (prompt: InvokeAI.Prompt): string => { - if (typeof prompt === 'string') { - return prompt; - } - - if (prompt.length === 1) { - return prompt[0].prompt; - } - - return prompt - .map( - (promptItem: InvokeAI.PromptItem): string => - `${promptItem.prompt}:${promptItem.weight}` - ) - .join(' '); -}; - -export default promptToString; diff --git a/invokeai/frontend/web/src/common/util/seedWeightPairs.ts b/invokeai/frontend/web/src/common/util/seedWeightPairs.ts index 3a8af5c11d..564f66c1e3 100644 --- a/invokeai/frontend/web/src/common/util/seedWeightPairs.ts +++ b/invokeai/frontend/web/src/common/util/seedWeightPairs.ts @@ -1,68 +1,71 @@ -import * as InvokeAI from 'app/types/invokeai'; +// TODO: Restore variations +// Support code from v2.3 in here. -export const stringToSeedWeights = ( - string: string -): InvokeAI.SeedWeights | boolean => { - const stringPairs = string.split(','); - const arrPairs = stringPairs.map((p) => p.split(':')); - const pairs = arrPairs.map((p: Array): InvokeAI.SeedWeightPair => { - return { seed: Number(p[0]), weight: Number(p[1]) }; - }); +// export const stringToSeedWeights = ( +// string: string +// ): InvokeAI.SeedWeights | boolean => { +// const stringPairs = string.split(','); +// const arrPairs = stringPairs.map((p) => p.split(':')); +// const pairs = arrPairs.map((p: Array): InvokeAI.SeedWeightPair => { +// return { seed: Number(p[0]), weight: Number(p[1]) }; +// }); - if (!validateSeedWeights(pairs)) { - return false; - } +// if (!validateSeedWeights(pairs)) { +// return false; +// } - return pairs; -}; +// return pairs; +// }; -export const validateSeedWeights = ( - seedWeights: InvokeAI.SeedWeights | string -): boolean => { - return typeof seedWeights === 'string' - ? Boolean(stringToSeedWeights(seedWeights)) - : Boolean( - seedWeights.length && - !seedWeights.some((pair: InvokeAI.SeedWeightPair) => { - const { seed, weight } = pair; - const isSeedValid = !isNaN(parseInt(seed.toString(), 10)); - const isWeightValid = - !isNaN(parseInt(weight.toString(), 10)) && - weight >= 0 && - weight <= 1; - return !(isSeedValid && isWeightValid); - }) - ); -}; +// export const validateSeedWeights = ( +// seedWeights: InvokeAI.SeedWeights | string +// ): boolean => { +// return typeof seedWeights === 'string' +// ? Boolean(stringToSeedWeights(seedWeights)) +// : Boolean( +// seedWeights.length && +// !seedWeights.some((pair: InvokeAI.SeedWeightPair) => { +// const { seed, weight } = pair; +// const isSeedValid = !isNaN(parseInt(seed.toString(), 10)); +// const isWeightValid = +// !isNaN(parseInt(weight.toString(), 10)) && +// weight >= 0 && +// weight <= 1; +// return !(isSeedValid && isWeightValid); +// }) +// ); +// }; -export const seedWeightsToString = ( - seedWeights: InvokeAI.SeedWeights -): string => { - return seedWeights.reduce((acc, pair, i, arr) => { - const { seed, weight } = pair; - acc += `${seed}:${weight}`; - if (i !== arr.length - 1) { - acc += ','; - } - return acc; - }, ''); -}; +// export const seedWeightsToString = ( +// seedWeights: InvokeAI.SeedWeights +// ): string => { +// return seedWeights.reduce((acc, pair, i, arr) => { +// const { seed, weight } = pair; +// acc += `${seed}:${weight}`; +// if (i !== arr.length - 1) { +// acc += ','; +// } +// return acc; +// }, ''); +// }; -export const seedWeightsToArray = ( - seedWeights: InvokeAI.SeedWeights -): Array> => { - return seedWeights.map((pair: InvokeAI.SeedWeightPair) => [ - pair.seed, - pair.weight, - ]); -}; +// export const seedWeightsToArray = ( +// seedWeights: InvokeAI.SeedWeights +// ): Array> => { +// return seedWeights.map((pair: InvokeAI.SeedWeightPair) => [ +// pair.seed, +// pair.weight, +// ]); +// }; -export const stringToSeedWeightsArray = ( - string: string -): Array> => { - const stringPairs = string.split(','); - const arrPairs = stringPairs.map((p) => p.split(':')); - return arrPairs.map( - (p: Array): Array => [parseInt(p[0], 10), parseFloat(p[1])] - ); -}; +// export const stringToSeedWeightsArray = ( +// string: string +// ): Array> => { +// const stringPairs = string.split(','); +// const arrPairs = stringPairs.map((p) => p.split(':')); +// return arrPairs.map( +// (p: Array): Array => [parseInt(p[0], 10), parseFloat(p[1])] +// ); +// }; + +export default {}; diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts b/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts index 54eafd9780..48d59395ab 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts @@ -1,7 +1,5 @@ -import * as InvokeAI from 'app/types/invokeai'; import { IRect, Vector2d } from 'konva/lib/types'; import { RgbaColor } from 'react-colorful'; -import { ImageDTO } from 'services/api/types'; export const LAYER_NAMES_DICT = [ { label: 'Base', value: 'base' }, @@ -133,7 +131,6 @@ export interface CanvasState { cursorPosition: Vector2d | null; doesCanvasNeedScaling: boolean; futureLayerStates: CanvasLayerState[]; - intermediateImage?: InvokeAI.Image; isCanvasInitialized: boolean; isDrawing: boolean; isMaskEnabled: boolean; diff --git a/invokeai/frontend/web/src/features/gallery/components/GalleryProgressImage.tsx b/invokeai/frontend/web/src/features/gallery/components/GalleryProgressImage.tsx deleted file mode 100644 index 98f7db2726..0000000000 --- a/invokeai/frontend/web/src/features/gallery/components/GalleryProgressImage.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { Flex, Image, Spinner } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { systemSelector } from 'features/system/store/systemSelectors'; -import { memo } from 'react'; -import { gallerySelector } from '../store/gallerySelectors'; - -const selector = createSelector( - [systemSelector, gallerySelector], - (system, gallery) => { - const { shouldUseSingleGalleryColumn, galleryImageObjectFit } = gallery; - const { progressImage, shouldAntialiasProgressImage } = system; - - return { - progressImage, - shouldUseSingleGalleryColumn, - galleryImageObjectFit, - shouldAntialiasProgressImage, - }; - }, - defaultSelectorOptions -); - -const GalleryProgressImage = () => { - const { - progressImage, - shouldUseSingleGalleryColumn, - galleryImageObjectFit, - shouldAntialiasProgressImage, - } = useAppSelector(selector); - - if (!progressImage) { - return null; - } - - return ( - - - - - ); -}; - -export default memo(GalleryProgressImage); diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx index 285327a971..8da4adbcb3 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx @@ -159,6 +159,8 @@ const GalleryImageGrid = () => { ); } + + return null; }; export default memo(GalleryImageGrid); diff --git a/invokeai/frontend/web/src/features/gallery/store/boardSelectors.ts b/invokeai/frontend/web/src/features/gallery/store/boardSelectors.ts deleted file mode 100644 index 3dac2b6e50..0000000000 --- a/invokeai/frontend/web/src/features/gallery/store/boardSelectors.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; -import { selectBoardsAll } from './boardSlice'; - -export const boardSelector = (state: RootState) => state.boards.entities; - -export const searchBoardsSelector = createSelector( - (state: RootState) => state, - (state) => { - const { - boards: { searchText }, - } = state; - - if (!searchText) { - // If no search text provided, return all entities - return selectBoardsAll(state); - } - - return selectBoardsAll(state).filter((i) => - i.board_name.toLowerCase().includes(searchText.toLowerCase()) - ); - } -); diff --git a/invokeai/frontend/web/src/features/gallery/store/galleryPersistDenylist.ts b/invokeai/frontend/web/src/features/gallery/store/galleryPersistDenylist.ts index acef7d6fc1..9637cfedb4 100644 --- a/invokeai/frontend/web/src/features/gallery/store/galleryPersistDenylist.ts +++ b/invokeai/frontend/web/src/features/gallery/store/galleryPersistDenylist.ts @@ -5,13 +5,6 @@ import { initialGalleryState } from './gallerySlice'; */ export const galleryPersistDenylist: (keyof typeof initialGalleryState)[] = [ 'selection', - 'entities', - 'ids', - 'isLoading', - 'limit', - 'offset', 'selectedBoardId', 'galleryView', - 'total', - 'isInitialized', ]; diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index aaff5ba66c..b754018c1f 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -45,7 +45,7 @@ export const gallerySlice = createSlice({ initialState: initialGalleryState, reducers: { imageRangeEndSelected: (state, action: PayloadAction) => { - // MULTI SELECT LOGIC + // TODO: multiselect // const rangeEndImageName = action.payload; // const lastSelectedImage = state.selection[state.selection.length - 1]; // const filteredImages = selectFilteredImagesLocal(state); @@ -66,7 +66,7 @@ export const gallerySlice = createSlice({ // } }, imageSelectionToggled: (state, action: PayloadAction) => { - // MULTI SELECT LOGIC + // TODO: multiselect // if ( // state.selection.includes(action.payload) && // state.selection.length > 1 @@ -157,7 +157,6 @@ export const gallerySlice = createSlice({ }); export const { - imagesRemoved, imageRangeEndSelected, imageSelectionToggled, imageSelected, diff --git a/invokeai/frontend/web/src/features/lora/components/ParamLoraList.tsx b/invokeai/frontend/web/src/features/lora/components/ParamLoraList.tsx index 9bdd187de2..835c315e5c 100644 --- a/invokeai/frontend/web/src/features/lora/components/ParamLoraList.tsx +++ b/invokeai/frontend/web/src/features/lora/components/ParamLoraList.tsx @@ -18,7 +18,13 @@ const selector = createSelector( const ParamLoraList = () => { const { loras } = useAppSelector(selector); - return map(loras, (lora) => ); + return ( + <> + {map(loras, (lora) => ( + + ))} + + ); }; export default ParamLoraList; diff --git a/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx b/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx index 0699d000e9..796cdb010e 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ViewportControls.tsx @@ -59,13 +59,25 @@ const ViewportControls = () => { return ( - } /> + } + /> - } /> + } + /> - } /> + } + /> { } > } @@ -88,6 +101,7 @@ const ViewportControls = () => { } > } @@ -101,6 +115,7 @@ const ViewportControls = () => { } > } diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx index 984ad833a6..ab44bda16b 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx @@ -22,13 +22,16 @@ export default function ParamAdvancedCollapse() { const shouldShowAdvancedOptions = useAppSelector( (state: RootState) => state.ui.shouldShowAdvancedOptions ); + + if (!shouldShowAdvancedOptions) { + return null; + } + return ( - shouldShowAdvancedOptions && ( - - - - - - ) + + + + + ); } diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seamless/ParamSeamlessToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seamless/ParamSeamlessToggle.tsx deleted file mode 100644 index 1a3b046bcf..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seamless/ParamSeamlessToggle.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAISwitch from 'common/components/IAISwitch'; -import { setSeamless } from 'features/parameters/store/generationSlice'; -import { ChangeEvent } from 'react'; -import { useTranslation } from 'react-i18next'; - -/** - * Seamless tiling toggle - */ -const ParamSeamlessToggle = () => { - const dispatch = useAppDispatch(); - - const seamless = useAppSelector( - (state: RootState) => state.generation.seamless - ); - - const handleChangeSeamless = (e: ChangeEvent) => - dispatch(setSeamless(e.target.checked)); - - const { t } = useTranslation(); - - return ( - - ); -}; - -export default ParamSeamlessToggle; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedCollapse.tsx deleted file mode 100644 index 2867029f7e..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedCollapse.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Flex } from '@chakra-ui/react'; -import ParamSeed from './ParamSeed'; -import { memo, useCallback } from 'react'; -import ParamSeedShuffle from './ParamSeedShuffle'; -import { useTranslation } from 'react-i18next'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { createSelector } from '@reduxjs/toolkit'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { setShouldRandomizeSeed } from 'features/parameters/store/generationSlice'; -import IAICollapse from 'common/components/IAICollapse'; - -const selector = createSelector( - generationSelector, - (generation) => { - const { shouldRandomizeSeed } = generation; - - return { shouldRandomizeSeed }; - }, - defaultSelectorOptions -); - -const ParamSeedSettings = () => { - const { t } = useTranslation(); - const dispatch = useAppDispatch(); - const { shouldRandomizeSeed } = useAppSelector(selector); - - const handleToggle = useCallback( - () => dispatch(setShouldRandomizeSeed(!shouldRandomizeSeed)), - [dispatch, shouldRandomizeSeed] - ); - - return ( - - - - - - - ); -}; - -export default memo(ParamSeedSettings); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationCollapse.tsx index 3cdfc3a06b..7ea248498d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationCollapse.tsx @@ -1,47 +1,51 @@ -import { Flex } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { stateSelector } from 'app/store/store'; -import { useAppSelector } from 'app/store/storeHooks'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import IAICollapse from 'common/components/IAICollapse'; -import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; -import { memo } from 'react'; -import { useTranslation } from 'react-i18next'; -import ParamVariationAmount from './ParamVariationAmount'; -import { ParamVariationToggle } from './ParamVariationToggle'; -import ParamVariationWeights from './ParamVariationWeights'; +// TODO: variations -const selector = createSelector( - stateSelector, - (state) => { - const activeLabel = state.generation.shouldGenerateVariations - ? 'Enabled' - : undefined; +// import { Flex } from '@chakra-ui/react'; +// import { createSelector } from '@reduxjs/toolkit'; +// import { stateSelector } from 'app/store/store'; +// import { useAppSelector } from 'app/store/storeHooks'; +// import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; +// import IAICollapse from 'common/components/IAICollapse'; +// import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; +// import { memo } from 'react'; +// import { useTranslation } from 'react-i18next'; +// import ParamVariationAmount from './ParamVariationAmount'; +// import { ParamVariationToggle } from './ParamVariationToggle'; +// import ParamVariationWeights from './ParamVariationWeights'; - return { activeLabel }; - }, - defaultSelectorOptions -); +// const selector = createSelector( +// stateSelector, +// (state) => { +// const activeLabel = state.generation.shouldGenerateVariations +// ? 'Enabled' +// : undefined; -const ParamVariationCollapse = () => { - const { t } = useTranslation(); - const { activeLabel } = useAppSelector(selector); +// return { activeLabel }; +// }, +// defaultSelectorOptions +// ); - const isVariationEnabled = useFeatureStatus('variation').isFeatureEnabled; +// const ParamVariationCollapse = () => { +// const { t } = useTranslation(); +// const { activeLabel } = useAppSelector(selector); - if (!isVariationEnabled) { - return null; - } +// const isVariationEnabled = useFeatureStatus('variation').isFeatureEnabled; - return ( - - - - - - - - ); -}; +// if (!isVariationEnabled) { +// return null; +// } -export default memo(ParamVariationCollapse); +// return ( +// +// +// +// +// +// +// +// ); +// }; + +// export default memo(ParamVariationCollapse); + +export default {}; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationWeights.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationWeights.tsx index 30876597a8..45029e8536 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationWeights.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationWeights.tsx @@ -1,37 +1,41 @@ -import { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAIInput from 'common/components/IAIInput'; -import { validateSeedWeights } from 'common/util/seedWeightPairs'; -import { setSeedWeights } from 'features/parameters/store/generationSlice'; -import { ChangeEvent } from 'react'; -import { useTranslation } from 'react-i18next'; +// TODO: variations -export default function ParamVariationWeights() { - const seedWeights = useAppSelector( - (state: RootState) => state.generation.seedWeights - ); +// import { RootState } from 'app/store/store'; +// import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +// import IAIInput from 'common/components/IAIInput'; +// import { validateSeedWeights } from 'common/util/seedWeightPairs'; +// import { setSeedWeights } from 'features/parameters/store/generationSlice'; +// import { ChangeEvent } from 'react'; +// import { useTranslation } from 'react-i18next'; - const shouldGenerateVariations = useAppSelector( - (state: RootState) => state.generation.shouldGenerateVariations - ); +// export default function ParamVariationWeights() { +// const seedWeights = useAppSelector( +// (state: RootState) => state.generation.seedWeights +// ); - const { t } = useTranslation(); +// const shouldGenerateVariations = useAppSelector( +// (state: RootState) => state.generation.shouldGenerateVariations +// ); - const dispatch = useAppDispatch(); +// const { t } = useTranslation(); - const handleChangeSeedWeights = (e: ChangeEvent) => - dispatch(setSeedWeights(e.target.value)); +// const dispatch = useAppDispatch(); - return ( - - ); -} +// const handleChangeSeedWeights = (e: ChangeEvent) => +// dispatch(setSeedWeights(e.target.value)); + +// return ( +// +// ); +// } + +export default {}; diff --git a/invokeai/frontend/web/src/features/system/store/systemSelectors.ts b/invokeai/frontend/web/src/features/system/store/systemSelectors.ts index 0d53da85e6..900d8e0bd6 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSelectors.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSelectors.ts @@ -1,47 +1,11 @@ import { createSelector } from '@reduxjs/toolkit'; import { RootState } from 'app/store/store'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { pickBy, reduce } from 'lodash-es'; export const systemSelector = (state: RootState) => state.system; export const toastQueueSelector = (state: RootState) => state.system.toastQueue; -export const activeModelSelector = createSelector( - systemSelector, - (system) => { - const { model_list } = system; - const activeModel = reduce( - model_list, - (acc, model, key) => { - if (model.status === 'active') { - acc = key; - } - return acc; - }, - '' - ); - return { ...model_list[activeModel], name: activeModel }; - }, - defaultSelectorOptions -); - -export const diffusersModelsSelector = createSelector( - systemSelector, - (system) => { - const { model_list } = system; - - const diffusersModels = pickBy(model_list, (model, key) => { - if (model.format === 'diffusers') { - return { name: key, ...model }; - } - }); - - return diffusersModels; - }, - defaultSelectorOptions -); - export const languageSelector = createSelector( systemSelector, (system) => system.language, diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index 12955092de..aca126bb13 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -74,7 +74,8 @@ export interface SystemState { */ consoleLogLevel: InvokeLogLevel; shouldLogToConsole: boolean; - statusTranslationKey: any; + // TODO: probably better to not store keys here, should just be a string that maps to the translation key + statusTranslationKey: string; /** * When a session is canceled, its ID is stored here until a new session is created. */ @@ -125,7 +126,7 @@ export const systemSlice = createSlice({ setIsProcessing: (state, action: PayloadAction) => { state.isProcessing = action.payload; }, - setCurrentStatus: (state, action: any) => { + setCurrentStatus: (state, action: PayloadAction) => { state.statusTranslationKey = action.payload; }, setShouldConfirmOnDelete: (state, action: PayloadAction) => { @@ -362,7 +363,7 @@ export const systemSlice = createSlice({ * Session Invoked - REJECTED * Session Created - REJECTED */ - builder.addMatcher(isAnySessionRejected, (state, action) => { + builder.addMatcher(isAnySessionRejected, (state) => { state.isProcessing = false; state.isCancelable = false; state.isCancelScheduled = false; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx deleted file mode 100644 index 811660c174..0000000000 --- a/invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { Box, Flex } from '@chakra-ui/react'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; -import InitialImageDisplay from 'features/parameters/components/Parameters/ImageToImage/InitialImageDisplay'; -import { memo, useCallback, useRef } from 'react'; -import { - ImperativePanelGroupHandle, - Panel, - PanelGroup, -} from 'react-resizable-panels'; -import ResizeHandle from '../ResizeHandle'; -import TextToImageTabMain from '../TextToImage/TextToImageTabMain'; -import BatchManager from 'features/batch/components/BatchManager'; - -const ImageToImageTab = () => { - const dispatch = useAppDispatch(); - const panelGroupRef = useRef(null); - - const handleDoubleClickHandle = useCallback(() => { - if (!panelGroupRef.current) { - return; - } - - panelGroupRef.current.setLayout([50, 50]); - }, []); - - return ( - - - - ); -}; - -export default memo(ImageToImageTab); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabParameters.tsx index 87e19993d7..9de6a74ec0 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabParameters.tsx @@ -7,9 +7,8 @@ import ParamPositiveConditioning from 'features/parameters/components/Parameters import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse'; import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse'; import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse'; -import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; +// import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; -import { memo } from 'react'; import ImageToImageTabCoreParameters from './ImageToImageTabCoreParameters'; const ImageToImageTabParameters = () => { @@ -22,7 +21,7 @@ const ImageToImageTabParameters = () => { - + {/* */} @@ -31,4 +30,4 @@ const ImageToImageTabParameters = () => { ); }; -export default memo(ImageToImageTabParameters); +export default ImageToImageTabParameters; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx index 315e221366..bcb0e02298 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx @@ -168,7 +168,9 @@ export default function FoundModelsList() { }; const renderFoundModels = () => { - if (!searchFolder) return; + if (!searchFolder) { + return null; + } if (!foundModels || foundModels.length === 0) { return ( @@ -242,7 +244,7 @@ const foundModelsFilter = ( const filteredModels: SearchFolderResponse = []; forEach(data, (model) => { if (!model) { - return; + return null; } if (model.includes(nameFilter)) { diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/ScanAdvancedAddModels.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/ScanAdvancedAddModels.tsx index 3ae4773009..32906c3396 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/ScanAdvancedAddModels.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/ScanAdvancedAddModels.tsx @@ -32,66 +32,68 @@ export default function ScanAdvancedAddModels() { const dispatch = useAppDispatch(); + if (!advancedAddScanModel) { + return null; + } + return ( - advancedAddScanModel && ( - - - - {isCheckpoint || advancedAddMode === 'checkpoint' - ? 'Add Checkpoint Model' - : 'Add Diffusers Model'} - - } - aria-label="Close Advanced" - onClick={() => dispatch(setAdvancedAddScanModel(null))} - size="sm" - /> - - { - if (!v) return; - setAdvancedAddMode(v as ManualAddMode); - if (v === 'checkpoint') { - setIsCheckpoint(true); - } else { - setIsCheckpoint(false); - } - }} + + + + {isCheckpoint || advancedAddMode === 'checkpoint' + ? 'Add Checkpoint Model' + : 'Add Diffusers Model'} + + } + aria-label="Close Advanced" + onClick={() => dispatch(setAdvancedAddScanModel(null))} + size="sm" /> - {isCheckpoint ? ( - - ) : ( - - )} - - ) + + { + if (!v) return; + setAdvancedAddMode(v as ManualAddMode); + if (v === 'checkpoint') { + setIsCheckpoint(true); + } else { + setIsCheckpoint(false); + } + }} + /> + {isCheckpoint ? ( + + ) : ( + + )} + ); } diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SearchModelsOld.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SearchModelsOld.tsx deleted file mode 100644 index 3381cb85d3..0000000000 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SearchModelsOld.tsx +++ /dev/null @@ -1,430 +0,0 @@ -import IAIButton from 'common/components/IAIButton'; -import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox'; -import IAIIconButton from 'common/components/IAIIconButton'; -import React from 'react'; - -import { - Badge, - Flex, - FormControl, - HStack, - Radio, - RadioGroup, - Spacer, - Text, -} from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { systemSelector } from 'features/system/store/systemSelectors'; -import { useTranslation } from 'react-i18next'; - -import { FaSearch, FaTrash } from 'react-icons/fa'; - -// import { addNewModel, searchForModels } from 'app/socketio/actions'; -import { - setFoundModels, - setSearchFolder, -} from 'features/system/store/systemSlice'; -import { setShouldShowExistingModelsInSearch } from 'features/ui/store/uiSlice'; - -import type { FoundModel } from 'app/types/invokeai'; -import type { RootState } from 'app/store/store'; -import IAIInput from 'common/components/IAIInput'; -import { Field, Formik } from 'formik'; -import { forEach, remove } from 'lodash-es'; -import type { ChangeEvent, ReactNode } from 'react'; -import IAIForm from 'common/components/IAIForm'; - -const existingModelsSelector = createSelector([systemSelector], (system) => { - const { model_list } = system; - - const existingModels: string[] = []; - - forEach(model_list, (value) => { - existingModels.push(value.weights); - }); - - return existingModels; -}); - -interface SearchModelEntry { - model: FoundModel; - modelsToAdd: string[]; - setModelsToAdd: React.Dispatch>; -} - -function SearchModelEntry({ - model, - modelsToAdd, - setModelsToAdd, -}: SearchModelEntry) { - const { t } = useTranslation(); - const existingModels = useAppSelector(existingModelsSelector); - - const foundModelsChangeHandler = (e: ChangeEvent) => { - if (!modelsToAdd.includes(e.target.value)) { - setModelsToAdd([...modelsToAdd, e.target.value]); - } else { - setModelsToAdd(remove(modelsToAdd, (v) => v !== e.target.value)); - } - }; - - return ( - - - {model.name}} - isChecked={modelsToAdd.includes(model.name)} - isDisabled={existingModels.includes(model.location)} - onChange={foundModelsChangeHandler} - > - {existingModels.includes(model.location) && ( - {t('modelManager.modelExists')} - )} - - - {model.location} - - - ); -} - -export default function SearchModels() { - const dispatch = useAppDispatch(); - - const { t } = useTranslation(); - - const searchFolder = useAppSelector( - (state: RootState) => state.system.searchFolder - ); - - const foundModels = useAppSelector( - (state: RootState) => state.system.foundModels - ); - - const existingModels = useAppSelector(existingModelsSelector); - - const shouldShowExistingModelsInSearch = useAppSelector( - (state: RootState) => state.ui.shouldShowExistingModelsInSearch - ); - - const isProcessing = useAppSelector( - (state: RootState) => state.system.isProcessing - ); - - const [modelsToAdd, setModelsToAdd] = React.useState([]); - const [modelType, setModelType] = React.useState('v1'); - const [pathToConfig, setPathToConfig] = React.useState(''); - - const resetSearchModelHandler = () => { - dispatch(setSearchFolder(null)); - dispatch(setFoundModels(null)); - setModelsToAdd([]); - }; - - const findModelsHandler = (values: { checkpointFolder: string }) => { - dispatch(searchForModels(values.checkpointFolder)); - }; - - const addAllToSelected = () => { - setModelsToAdd([]); - if (foundModels) { - foundModels.forEach((model) => { - if (!existingModels.includes(model.location)) { - setModelsToAdd((currentModels) => { - return [...currentModels, model.name]; - }); - } - }); - } - }; - - const removeAllFromSelected = () => { - setModelsToAdd([]); - }; - - const addSelectedModels = () => { - const modelsToBeAdded = foundModels?.filter((foundModel) => - modelsToAdd.includes(foundModel.name) - ); - - const configFiles = { - v1: 'configs/stable-diffusion/v1-inference.yaml', - v2_base: 'configs/stable-diffusion/v2-inference-v.yaml', - v2_768: 'configs/stable-diffusion/v2-inference-v.yaml', - inpainting: 'configs/stable-diffusion/v1-inpainting-inference.yaml', - custom: pathToConfig, - }; - - modelsToBeAdded?.forEach((model) => { - const modelFormat = { - name: model.name, - description: '', - config: configFiles[modelType as keyof typeof configFiles], - weights: model.location, - vae: '', - width: 512, - height: 512, - default: false, - format: 'ckpt', - }; - dispatch(addNewModel(modelFormat)); - }); - setModelsToAdd([]); - }; - - const renderFoundModels = () => { - const newFoundModels: ReactNode[] = []; - const existingFoundModels: ReactNode[] = []; - - if (foundModels) { - foundModels.forEach((model, index) => { - if (existingModels.includes(model.location)) { - existingFoundModels.push( - - ); - } else { - newFoundModels.push( - - ); - } - }); - } - - return ( - - {newFoundModels} - {shouldShowExistingModelsInSearch && existingFoundModels} - - ); - }; - - return ( - <> - {searchFolder ? ( - - - - {t('modelManager.checkpointFolder')} - - {searchFolder} - - - } - fontSize={18} - disabled={isProcessing} - onClick={() => dispatch(searchForModels(searchFolder))} - /> - } - onClick={resetSearchModelHandler} - /> - - ) : ( - { - findModelsHandler(values); - }} - > - {({ handleSubmit }) => ( - - - - - - } - aria-label={t('modelManager.findModels')} - tooltip={t('modelManager.findModels')} - type="submit" - disabled={isProcessing} - px={8} - > - {t('modelManager.findModels')} - - - - )} - - )} - {foundModels && ( - - -

- {t('modelManager.modelsFound')}: {foundModels.length} -

-

- {t('modelManager.selected')}: {modelsToAdd.length} -

-
- - - - {t('modelManager.selectAll')} - - - {t('modelManager.deselectAll')} - - - dispatch( - setShouldShowExistingModelsInSearch( - !shouldShowExistingModelsInSearch - ) - ) - } - /> - - - - {t('modelManager.addSelected')} - - - - - - - {t('modelManager.pickModelType')} - - setModelType(v)} - defaultValue="v1" - name="model_type" - > - - - {t('modelManager.v1')} - - - {t('modelManager.v2_base')} - - - {t('modelManager.v2_768')} - - - {t('modelManager.inpainting')} - - - {t('modelManager.customConfig')} - - - - - - {modelType === 'custom' && ( - - - {t('modelManager.pathToCustomConfig')} - - { - if (e.target.value !== '') setPathToConfig(e.target.value); - }} - width="full" - /> - - )} - - - - {foundModels.length > 0 ? ( - renderFoundModels() - ) : ( - - {t('modelManager.noModelsFound')} - - )} - -
- )} - - ); -} diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabParameters.tsx index 3d3fd87851..8b6fb6f46c 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabParameters.tsx @@ -7,9 +7,8 @@ import ParamPositiveConditioning from 'features/parameters/components/Parameters import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse'; import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse'; import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse'; -import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; +// import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; -import { memo } from 'react'; import TextToImageTabCoreParameters from './TextToImageTabCoreParameters'; const TextToImageTabParameters = () => { @@ -22,7 +21,7 @@ const TextToImageTabParameters = () => { - + {/* */} @@ -31,4 +30,4 @@ const TextToImageTabParameters = () => { ); }; -export default memo(TextToImageTabParameters); +export default TextToImageTabParameters; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx index e413ad7ab2..95270c6bbc 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx @@ -7,9 +7,8 @@ import ParamControlNetCollapse from 'features/parameters/components/Parameters/C import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning'; import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning'; import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse'; -import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; +// import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; -import { memo } from 'react'; import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters'; const UnifiedCanvasParameters = () => { @@ -22,7 +21,7 @@ const UnifiedCanvasParameters = () => { - + {/* */} @@ -31,4 +30,4 @@ const UnifiedCanvasParameters = () => { ); }; -export default memo(UnifiedCanvasParameters); +export default UnifiedCanvasParameters; diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index ccce10f5c4..c653e40368 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -4,7 +4,7 @@ import { initialImageChanged } from 'features/parameters/store/generationSlice'; import { SchedulerParam } from 'features/parameters/types/parameterSchemas'; import { setActiveTabReducer } from './extraReducers'; import { InvokeTabName } from './tabMap'; -import { AddNewModelType, UIState } from './uiTypes'; +import { UIState } from './uiTypes'; export const initialUIState: UIState = { activeTab: 0, @@ -14,7 +14,6 @@ export const initialUIState: UIState = { shouldUseCanvasBetaLayout: false, shouldShowExistingModelsInSearch: false, shouldUseSliders: false, - addNewModelUIOption: null, shouldPinGallery: true, shouldShowGallery: true, shouldHidePreview: false, @@ -57,9 +56,6 @@ export const uiSlice = createSlice({ setShouldUseSliders: (state, action: PayloadAction) => { state.shouldUseSliders = action.payload; }, - setAddNewModelUIOption: (state, action: PayloadAction) => { - state.addNewModelUIOption = action.payload; - }, setShouldShowGallery: (state, action: PayloadAction) => { state.shouldShowGallery = action.payload; }, @@ -124,7 +120,6 @@ export const { setShouldUseCanvasBetaLayout, setShouldShowExistingModelsInSearch, setShouldUseSliders, - setAddNewModelUIOption, setShouldHidePreview, setShouldShowGallery, togglePanels, diff --git a/invokeai/frontend/web/src/services/api/models/HedImageprocessorInvocation.ts b/invokeai/frontend/web/src/services/api/models/HedImageprocessorInvocation.ts deleted file mode 100644 index 387e8c8634..0000000000 --- a/invokeai/frontend/web/src/services/api/models/HedImageprocessorInvocation.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -import type { ImageField } from './ImageField'; - -/** - * Applies HED edge detection to image - */ -export type HedImageProcessorInvocation = { - /** - * The id of this node. Must be unique among all nodes. - */ - id: string; - /** - * Whether or not this node is an intermediate node. - */ - is_intermediate?: boolean; - type?: 'hed_image_processor'; - /** - * The image to process - */ - image?: ImageField; - /** - * The pixel resolution for detection - */ - detect_resolution?: number; - /** - * The pixel resolution for the output image - */ - image_resolution?: number; - /** - * Whether to use scribble mode - */ - scribble?: boolean; -}; From 6452d0fc28fa9635a4b4b22f884253bec3d8c477 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 22 Jul 2023 22:48:39 +1000 Subject: [PATCH 3/4] fix(ui): fix all circular dependencies --- invokeai/frontend/web/scripts/typegen.ts | 2 +- .../components/ImageDnd/ImageDndContext.tsx | 1 - .../app/components/ImageDnd/typesafeDnd.tsx | 2 +- .../web/src/app/components/Toaster.ts | 22 +----- invokeai/frontend/web/src/app/constants.ts | 64 ----------------- .../addFirstListImagesListener.ts.ts | 6 +- .../listeners/boardAndImagesDeleted.ts | 2 +- .../listeners/boardIdSelected.ts | 6 +- .../listeners/imageDeleted.ts | 6 +- .../listeners/imageToDeleteSelected.ts | 4 +- .../listeners/initialImageSelected.ts | 2 +- .../listeners/modelSelected.ts | 6 +- .../socketio/socketInvocationComplete.ts | 2 +- invokeai/frontend/web/src/app/store/store.ts | 13 ++-- .../frontend/web/src/app/store/storeUtils.ts | 8 --- .../IAICanvasToolbar/IAICanvasBoundingBox.tsx | 9 ++- .../src/features/canvas/store/canvasSlice.ts | 7 +- .../controlNet/store/controlNetSlice.ts | 3 - .../ParamDynamicPromptsCombinatorial.tsx | 2 +- .../components/ParamDynamicPromptsEnabled.tsx | 2 +- .../ParamDynamicPromptsMaxPrompts.tsx | 5 +- .../{slice.ts => dynamicPromptsSlice.ts} | 7 -- .../Boards/BoardsList/GenericBoard.tsx | 2 +- .../components/Boards/DeleteBoardModal.tsx | 6 +- .../components/ImageGrid/GalleryImageGrid.tsx | 2 +- .../gallery/hooks/useNextPrevImage.ts | 6 +- .../src/features/gallery/store/boardSlice.ts | 3 - .../gallery/store/gallerySelectors.ts | 2 +- .../features/gallery/store/gallerySlice.ts | 27 +------ .../web/src/features/gallery/store/types.ts | 26 +++++++ .../web/src/features/gallery/store/util.ts | 55 -------------- .../components/DeleteImageModal.tsx | 8 +-- .../components/ImageUsageMessage.tsx | 4 +- .../features/imageDeletion/store/actions.ts | 8 +++ .../store/imageDeletionSelectors.ts | 55 ++++++++++++++ .../imageDeletion/store/imageDeletionSlice.ts | 72 +------------------ .../src/features/imageDeletion/store/types.ts | 6 ++ .../features/nodes/components/AddNodeMenu.tsx | 7 +- .../components/IAINode/IAINodeResizer.tsx | 2 +- .../features/nodes/components/NodeWrapper.tsx | 3 +- .../nodes/components/ui/ClearNodesButton.tsx | 2 +- .../nodes/components/ui/LoadNodesButton.tsx | 2 +- .../nodes/store/nodesPersistDenylist.ts | 2 +- .../src/features/nodes/store/nodesSlice.ts | 19 +---- .../web/src/features/nodes/store/types.ts | 16 +++++ .../web/src/features/nodes/types/constants.ts | 2 + .../Advanced/ParamAdvancedCollapse.tsx | 2 +- .../Parameters/Advanced/ParamClipSkip.tsx | 20 +----- .../BoundingBox/ParamBoundingBoxHeight.tsx | 13 ++-- .../BoundingBox/ParamBoundingBoxWidth.tsx | 13 ++-- .../ControlNet/ParamControlNetCollapse.tsx | 6 +- .../Parameters/Core/ParamAspectRatio.tsx | 4 +- .../Parameters/Core/ParamCFGScale.tsx | 9 +-- .../Parameters/Core/ParamHeight.tsx | 11 ++- .../Parameters/Core/ParamScheduler.tsx | 15 ++-- .../components/Parameters/Core/ParamSteps.tsx | 9 +-- .../components/Parameters/Core/ParamWidth.tsx | 12 ++-- .../ImageToImage/ImageToImageStrength.tsx | 8 +-- .../parameters/store/generationSlice.ts | 34 +++++---- .../features/parameters/types/constants.ts | 19 +++++ .../parameters/types/parameterSchemas.ts | 52 +++++++++++++- .../system/components/LanguagePicker.tsx | 27 ++----- .../SettingsClearIntermediates.tsx | 4 +- .../SettingsModal/SettingsModal.tsx | 35 ++------- .../SettingsModal/SettingsSchedulers.tsx | 12 ++-- .../components/SettingsModal/StyledFlex.tsx | 23 ++++++ .../src/features/system/store/constants.ts | 20 ++++++ .../src/features/system/store/systemSlice.ts | 5 +- .../web/src/features/system/util/makeToast.ts | 20 ++++++ .../AddModelsPanel/AdvancedAddCheckpoint.tsx | 2 +- .../AddModelsPanel/AdvancedAddDiffusers.tsx | 2 +- .../AddModelsPanel/FoundModelsList.tsx | 2 +- .../AddModelsPanel/SimpleAddModels.tsx | 2 +- .../subpanels/MergeModelsPanel.tsx | 2 +- .../ModelManagerPanel/CheckpointModelEdit.tsx | 2 +- .../ModelManagerPanel/DiffusersModelEdit.tsx | 2 +- .../ModelManagerPanel/ModelConvert.tsx | 2 +- .../ModelManagerPanel/ModelListItem.tsx | 2 +- .../SyncModelsButton.tsx | 2 +- .../web/src/features/ui/store/hotkeysSlice.ts | 3 - .../web/src/features/ui/store/uiSlice.ts | 10 --- .../web/src/features/ui/store/uiTypes.ts | 2 - .../web/src/services/api/endpoints/boards.ts | 3 +- .../web/src/services/api/endpoints/images.ts | 35 ++++++++- .../web/src/services/api/endpoints/util.ts | 51 ------------- .../src/services/api/hooks/useBoardName.ts | 2 +- .../src/services/api/hooks/useBoardTotal.ts | 2 +- .../web/src/services/api/thunks/session.ts | 11 ++- .../services/events/util/setEventListeners.ts | 4 +- 89 files changed, 446 insertions(+), 588 deletions(-) delete mode 100644 invokeai/frontend/web/src/app/store/storeUtils.ts rename invokeai/frontend/web/src/features/dynamicPrompts/store/{slice.ts => dynamicPromptsSlice.ts} (86%) create mode 100644 invokeai/frontend/web/src/features/gallery/store/types.ts delete mode 100644 invokeai/frontend/web/src/features/gallery/store/util.ts create mode 100644 invokeai/frontend/web/src/features/imageDeletion/store/actions.ts create mode 100644 invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSelectors.ts create mode 100644 invokeai/frontend/web/src/features/imageDeletion/store/types.ts create mode 100644 invokeai/frontend/web/src/features/nodes/store/types.ts create mode 100644 invokeai/frontend/web/src/features/system/components/SettingsModal/StyledFlex.tsx create mode 100644 invokeai/frontend/web/src/features/system/store/constants.ts create mode 100644 invokeai/frontend/web/src/features/system/util/makeToast.ts delete mode 100644 invokeai/frontend/web/src/services/api/endpoints/util.ts diff --git a/invokeai/frontend/web/scripts/typegen.ts b/invokeai/frontend/web/scripts/typegen.ts index 39d0b25d30..015ae918ab 100644 --- a/invokeai/frontend/web/scripts/typegen.ts +++ b/invokeai/frontend/web/scripts/typegen.ts @@ -10,7 +10,7 @@ async function main() { ); const types = await openapiTS(OPENAPI_URL, { exportType: true, - transform: (schemaObject, metadata) => { + transform: (schemaObject) => { if ('format' in schemaObject && schemaObject.format === 'binary') { return schemaObject.nullable ? 'Blob | null' : 'Blob'; } diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx index 91e274930c..24bdceac3a 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx @@ -39,7 +39,6 @@ const ImageDndContext = (props: ImageDndContextProps) => { const handleDragEnd = useCallback( (event: DragEndEvent) => { console.log('dragEnd', event.active.data.current); - const activeData = event.active.data.current; const overData = event.over?.data.current; if (!activeDragData || !overData) { return; diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx index 1b2b10c897..5f08466710 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx @@ -11,7 +11,7 @@ import { useDraggable as useOriginalDraggable, useDroppable as useOriginalDroppable, } from '@dnd-kit/core'; -import { BoardId } from 'features/gallery/store/gallerySlice'; +import { BoardId } from 'features/gallery/store/types'; import { ImageDTO } from 'services/api/types'; type BaseDropData = { diff --git a/invokeai/frontend/web/src/app/components/Toaster.ts b/invokeai/frontend/web/src/app/components/Toaster.ts index 66ba1d4925..dff2a7c7f5 100644 --- a/invokeai/frontend/web/src/app/components/Toaster.ts +++ b/invokeai/frontend/web/src/app/components/Toaster.ts @@ -1,28 +1,10 @@ -import { useToast, UseToastOptions } from '@chakra-ui/react'; +import { useToast } from '@chakra-ui/react'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { toastQueueSelector } from 'features/system/store/systemSelectors'; import { addToast, clearToastQueue } from 'features/system/store/systemSlice'; +import { MakeToastArg, makeToast } from 'features/system/util/makeToast'; import { useCallback, useEffect } from 'react'; -export type MakeToastArg = string | UseToastOptions; - -/** - * Makes a toast from a string or a UseToastOptions object. - * If a string is passed, the toast will have the status 'info' and will be closable with a duration of 2500ms. - */ -export const makeToast = (arg: MakeToastArg): UseToastOptions => { - if (typeof arg === 'string') { - return { - title: arg, - status: 'info', - isClosable: true, - duration: 2500, - }; - } - - return { status: 'info', isClosable: true, duration: 2500, ...arg }; -}; - /** * Logical component. Watches the toast queue and makes toasts when the queue is not empty. * @returns null diff --git a/invokeai/frontend/web/src/app/constants.ts b/invokeai/frontend/web/src/app/constants.ts index c52e3bd48f..1194ea467b 100644 --- a/invokeai/frontend/web/src/app/constants.ts +++ b/invokeai/frontend/web/src/app/constants.ts @@ -1,66 +1,2 @@ -// zod needs the array to be `as const` to infer the type correctly - -import { SchedulerParam } from 'features/parameters/types/parameterSchemas'; - -// this is the source of the `SchedulerParam` type, which is generated by zod -export const SCHEDULER_NAMES_AS_CONST = [ - 'euler', - 'deis', - 'ddim', - 'ddpm', - 'dpmpp_2s', - 'dpmpp_2m', - 'dpmpp_2m_sde', - 'dpmpp_sde', - 'heun', - 'kdpm_2', - 'lms', - 'pndm', - 'unipc', - 'euler_k', - 'dpmpp_2s_k', - 'dpmpp_2m_k', - 'dpmpp_2m_sde_k', - 'dpmpp_sde_k', - 'heun_k', - 'lms_k', - 'euler_a', - 'kdpm_2_a', -] as const; - -export const DEFAULT_SCHEDULER_NAME = 'euler'; - -export const SCHEDULER_NAMES: SchedulerParam[] = [...SCHEDULER_NAMES_AS_CONST]; - -export const SCHEDULER_LABEL_MAP: Record = { - euler: 'Euler', - deis: 'DEIS', - ddim: 'DDIM', - ddpm: 'DDPM', - dpmpp_sde: 'DPM++ SDE', - dpmpp_2s: 'DPM++ 2S', - dpmpp_2m: 'DPM++ 2M', - dpmpp_2m_sde: 'DPM++ 2M SDE', - heun: 'Heun', - kdpm_2: 'KDPM 2', - lms: 'LMS', - pndm: 'PNDM', - unipc: 'UniPC', - euler_k: 'Euler Karras', - dpmpp_sde_k: 'DPM++ SDE Karras', - dpmpp_2s_k: 'DPM++ 2S Karras', - dpmpp_2m_k: 'DPM++ 2M Karras', - dpmpp_2m_sde_k: 'DPM++ 2M SDE Karras', - heun_k: 'Heun Karras', - lms_k: 'LMS Karras', - euler_a: 'Euler Ancestral', - kdpm_2_a: 'KDPM 2 Ancestral', -}; - -export type Scheduler = (typeof SCHEDULER_NAMES)[number]; - export const NUMPY_RAND_MIN = 0; - export const NUMPY_RAND_MAX = 2147483647; - -export const NODE_MIN_WIDTH = 250; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts index 8a1dd2943c..315dd2f5f9 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts @@ -1,8 +1,6 @@ import { createAction } from '@reduxjs/toolkit'; -import { - IMAGE_CATEGORIES, - imageSelected, -} from 'features/gallery/store/gallerySlice'; +import { imageSelected } from 'features/gallery/store/gallerySlice'; +import { IMAGE_CATEGORIES } from 'features/gallery/store/types'; import { ImageCache, getListImagesUrl, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts index 8c5572f399..5320846e15 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts @@ -1,6 +1,6 @@ import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; -import { getImageUsage } from 'features/imageDeletion/store/imageDeletionSlice'; +import { getImageUsage } from 'features/imageDeletion/store/imageDeletionSelectors'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; import { startAppListening } from '..'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts index bf4dc7918c..f9c856d6cb 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts @@ -1,11 +1,13 @@ import { isAnyOf } from '@reduxjs/toolkit'; import { - ASSETS_CATEGORIES, - IMAGE_CATEGORIES, boardIdSelected, galleryViewChanged, imageSelected, } from 'features/gallery/store/gallerySlice'; +import { + ASSETS_CATEGORIES, + IMAGE_CATEGORIES, +} from 'features/gallery/store/types'; import { imagesApi } from 'services/api/endpoints/images'; import { startAppListening } from '..'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts index 716b31768c..2643a461d7 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts @@ -3,10 +3,8 @@ import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors'; import { imageSelected } from 'features/gallery/store/gallerySlice'; -import { - imageDeletionConfirmed, - isModalOpenChanged, -} from 'features/imageDeletion/store/imageDeletionSlice'; +import { imageDeletionConfirmed } from 'features/imageDeletion/store/actions'; +import { isModalOpenChanged } from 'features/imageDeletion/store/imageDeletionSlice'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; import { clamp } from 'lodash-es'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts index 77ebd5c994..646cd259ad 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts @@ -1,8 +1,8 @@ +import { imageDeletionConfirmed } from 'features/imageDeletion/store/actions'; +import { selectImageUsage } from 'features/imageDeletion/store/imageDeletionSelectors'; import { - imageDeletionConfirmed, imageToDeleteSelected, isModalOpenChanged, - selectImageUsage, } from 'features/imageDeletion/store/imageDeletionSlice'; import { startAppListening } from '..'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts index 0cd68cf6fa..17a52f2bfc 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts @@ -1,7 +1,7 @@ -import { makeToast } from 'app/components/Toaster'; import { initialImageSelected } from 'features/parameters/store/actions'; import { initialImageChanged } from 'features/parameters/store/generationSlice'; import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; import { t } from 'i18next'; import { startAppListening } from '..'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts index 6612963096..7880386057 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts @@ -1,5 +1,5 @@ -import { makeToast } from 'app/components/Toaster'; -import { $logger, logger } from 'app/logging/logger'; +import { logger } from 'app/logging/logger'; +import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice'; import { loraRemoved } from 'features/lora/store/loraSlice'; import { modelSelected } from 'features/parameters/store/actions'; import { @@ -8,9 +8,9 @@ import { } from 'features/parameters/store/generationSlice'; import { zMainModel } from 'features/parameters/types/parameterSchemas'; import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; import { forEach } from 'lodash-es'; import { startAppListening } from '..'; -import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice'; export const addModelSelectedListener = () => { startAppListening({ diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts index 1ba653dba3..174a7de075 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts @@ -2,11 +2,11 @@ import { logger } from 'app/logging/logger'; import { parseify } from 'common/util/serialize'; import { addImageToStagingArea } from 'features/canvas/store/canvasSlice'; import { - IMAGE_CATEGORIES, boardIdSelected, galleryViewChanged, imageSelected, } from 'features/gallery/store/gallerySlice'; +import { IMAGE_CATEGORIES } from 'features/gallery/store/types'; import { progressImageSet } from 'features/system/store/systemSlice'; import { imagesAdapter, imagesApi } from 'services/api/endpoints/images'; import { isImageOutput } from 'services/api/guards'; diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 4725a2f921..ad128a0fec 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -4,14 +4,11 @@ import { autoBatchEnhancer, combineReducers, configureStore, + createAsyncThunk, } from '@reduxjs/toolkit'; - -import dynamicMiddlewares from 'redux-dynamic-middlewares'; -import { rememberEnhancer, rememberReducer } from 'redux-remember'; - import canvasReducer from 'features/canvas/store/canvasSlice'; import controlNetReducer from 'features/controlNet/store/controlNetSlice'; -import dynamicPromptsReducer from 'features/dynamicPrompts/store/slice'; +import dynamicPromptsReducer from 'features/dynamicPrompts/store/dynamicPromptsSlice'; import boardsReducer from 'features/gallery/store/boardSlice'; import galleryReducer from 'features/gallery/store/gallerySlice'; import imageDeletionReducer from 'features/imageDeletion/store/imageDeletionSlice'; @@ -24,9 +21,8 @@ import systemReducer from 'features/system/store/systemSlice'; import modelmanagerReducer from 'features/ui/components/tabs/ModelManager/store/modelManagerSlice'; import hotkeysReducer from 'features/ui/store/hotkeysSlice'; import uiReducer from 'features/ui/store/uiSlice'; - -import { listenerMiddleware } from './middleware/listenerMiddleware'; - +import dynamicMiddlewares from 'redux-dynamic-middlewares'; +import { rememberEnhancer, rememberReducer } from 'redux-remember'; import { api } from 'services/api'; import { LOCALSTORAGE_PREFIX } from './constants'; import { serialize } from './enhancers/reduxRemember/serialize'; @@ -34,6 +30,7 @@ import { unserialize } from './enhancers/reduxRemember/unserialize'; import { actionSanitizer } from './middleware/devtools/actionSanitizer'; import { actionsDenylist } from './middleware/devtools/actionsDenylist'; import { stateSanitizer } from './middleware/devtools/stateSanitizer'; +import { listenerMiddleware } from './middleware/listenerMiddleware'; const allReducers = { canvas: canvasReducer, diff --git a/invokeai/frontend/web/src/app/store/storeUtils.ts b/invokeai/frontend/web/src/app/store/storeUtils.ts deleted file mode 100644 index 1ccaad9f89..0000000000 --- a/invokeai/frontend/web/src/app/store/storeUtils.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { createAsyncThunk } from '@reduxjs/toolkit'; -import { AppDispatch, RootState } from 'app/store/store'; - -// https://redux-toolkit.js.org/usage/usage-with-typescript#defining-a-pre-typed-createasyncthunk -export const createAppAsyncThunk = createAsyncThunk.withTypes<{ - state: RootState; - dispatch: AppDispatch; -}>(); diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx index 3086e001c2..41c281d259 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasToolbar/IAICanvasBoundingBox.tsx @@ -1,10 +1,10 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { roundDownToMultiple, roundToMultiple, } from 'common/util/roundDownToMultiple'; -import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { setBoundingBoxCoordinates, setBoundingBoxDimensions, @@ -13,7 +13,6 @@ import { setIsTransformingBoundingBox, setShouldSnapToGrid, } from 'features/canvas/store/canvasSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import Konva from 'konva'; import { GroupConfig } from 'konva/lib/Group'; import { KonvaEventObject } from 'konva/lib/Node'; @@ -25,8 +24,8 @@ import { useHotkeys } from 'react-hotkeys-hook'; import { Group, Rect, Transformer } from 'react-konva'; const boundingBoxPreviewSelector = createSelector( - [canvasSelector, uiSelector], - (canvas, ui) => { + [stateSelector], + ({ canvas, generation }) => { const { boundingBoxCoordinates, boundingBoxDimensions, @@ -38,7 +37,7 @@ const boundingBoxPreviewSelector = createSelector( shouldSnapToGrid, } = canvas; - const { aspectRatio } = ui; + const { aspectRatio } = generation; return { boundingBoxCoordinates, diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts index 550cfff4bc..54ebfa2934 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts @@ -4,14 +4,13 @@ import { roundDownToMultiple, roundToMultiple, } from 'common/util/roundDownToMultiple'; -import { IRect, Vector2d } from 'konva/lib/types'; -import { clamp, cloneDeep } from 'lodash-es'; -// +import { setAspectRatio } from 'features/parameters/store/generationSlice'; import { setActiveTab, - setAspectRatio, setShouldUseCanvasBetaLayout, } from 'features/ui/store/uiSlice'; +import { IRect, Vector2d } from 'konva/lib/types'; +import { clamp, cloneDeep } from 'lodash-es'; import { RgbaColor } from 'react-colorful'; import { sessionCanceled } from 'services/api/thunks/session'; import { ImageDTO } from 'services/api/types'; diff --git a/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts b/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts index 2f8668115a..196023491c 100644 --- a/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts +++ b/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts @@ -1,5 +1,4 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; import { ControlNetModelParam } from 'features/parameters/types/parameterSchemas'; import { cloneDeep, forEach } from 'lodash-es'; import { imagesApi } from 'services/api/endpoints/images'; @@ -365,5 +364,3 @@ export const { } = controlNetSlice.actions; export default controlNetSlice.reducer; - -export const controlNetSelector = (state: RootState) => state.controlNet; diff --git a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx index cb930acd3b..809ec0df10 100644 --- a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx +++ b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCombinatorial.tsx @@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISwitch from 'common/components/IAISwitch'; import { useCallback } from 'react'; -import { combinatorialToggled } from '../store/slice'; +import { combinatorialToggled } from '../store/dynamicPromptsSlice'; const selector = createSelector( stateSelector, diff --git a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsEnabled.tsx b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsEnabled.tsx index 7a3b335659..f92fa410f2 100644 --- a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsEnabled.tsx +++ b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsEnabled.tsx @@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISwitch from 'common/components/IAISwitch'; import { useCallback } from 'react'; -import { isEnabledToggled } from '../store/slice'; +import { isEnabledToggled } from '../store/dynamicPromptsSlice'; const selector = createSelector( stateSelector, diff --git a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsMaxPrompts.tsx b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsMaxPrompts.tsx index d8b5721fbe..5bee317d22 100644 --- a/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsMaxPrompts.tsx +++ b/invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsMaxPrompts.tsx @@ -4,7 +4,10 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider from 'common/components/IAISlider'; import { useCallback } from 'react'; -import { maxPromptsChanged, maxPromptsReset } from '../store/slice'; +import { + maxPromptsChanged, + maxPromptsReset, +} from '../store/dynamicPromptsSlice'; const selector = createSelector( stateSelector, diff --git a/invokeai/frontend/web/src/features/dynamicPrompts/store/slice.ts b/invokeai/frontend/web/src/features/dynamicPrompts/store/dynamicPromptsSlice.ts similarity index 86% rename from invokeai/frontend/web/src/features/dynamicPrompts/store/slice.ts rename to invokeai/frontend/web/src/features/dynamicPrompts/store/dynamicPromptsSlice.ts index 8c33feb20c..d96c8ff0b0 100644 --- a/invokeai/frontend/web/src/features/dynamicPrompts/store/slice.ts +++ b/invokeai/frontend/web/src/features/dynamicPrompts/store/dynamicPromptsSlice.ts @@ -1,5 +1,4 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; export interface DynamicPromptsState { isEnabled: boolean; @@ -32,9 +31,6 @@ export const dynamicPromptsSlice = createSlice({ state.isEnabled = !state.isEnabled; }, }, - extraReducers: (builder) => { - // - }, }); export const { @@ -45,6 +41,3 @@ export const { } = dynamicPromptsSlice.actions; export default dynamicPromptsSlice.reducer; - -export const dynamicPromptsSelector = (state: RootState) => - state.dynamicPrompts; diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GenericBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GenericBoard.tsx index fa7f944a24..0d630c524d 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GenericBoard.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GenericBoard.tsx @@ -2,7 +2,7 @@ import { As, Badge, Flex } from '@chakra-ui/react'; import { TypesafeDroppableData } from 'app/components/ImageDnd/typesafeDnd'; import IAIDroppable from 'common/components/IAIDroppable'; import { IAINoContentFallback } from 'common/components/IAIImageFallback'; -import { BoardId } from 'features/gallery/store/gallerySlice'; +import { BoardId } from 'features/gallery/store/types'; import { ReactNode } from 'react'; import BoardContextMenu from '../BoardContextMenu'; diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/DeleteBoardModal.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/DeleteBoardModal.tsx index 3824fd6e0d..192c19c423 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/DeleteBoardModal.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/DeleteBoardModal.tsx @@ -11,14 +11,12 @@ import { } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { skipToken } from '@reduxjs/toolkit/dist/query'; +import { ImageUsage } from 'app/contexts/AddImageToBoardContext'; import { stateSelector } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import ImageUsageMessage from 'features/imageDeletion/components/ImageUsageMessage'; -import { - ImageUsage, - getImageUsage, -} from 'features/imageDeletion/store/imageDeletionSlice'; +import { getImageUsage } from 'features/imageDeletion/store/imageDeletionSelectors'; import { some } from 'lodash-es'; import { memo, useCallback, useMemo, useRef } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx index 8da4adbcb3..4a56fe0e9a 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/GalleryImageGrid.tsx @@ -2,8 +2,8 @@ import { Box, Flex } from '@chakra-ui/react'; import { useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import { IAINoContentFallback } from 'common/components/IAIImageFallback'; -import { IMAGE_LIMIT } from 'features/gallery//store/gallerySlice'; import { selectListImagesBaseQueryArgs } from 'features/gallery/store/gallerySelectors'; +import { IMAGE_LIMIT } from 'features/gallery/store/types'; import { UseOverlayScrollbarsParams, useOverlayScrollbars, diff --git a/invokeai/frontend/web/src/features/gallery/hooks/useNextPrevImage.ts b/invokeai/frontend/web/src/features/gallery/hooks/useNextPrevImage.ts index 7b4b8bed7b..f2572a23b5 100644 --- a/invokeai/frontend/web/src/features/gallery/hooks/useNextPrevImage.ts +++ b/invokeai/frontend/web/src/features/gallery/hooks/useNextPrevImage.ts @@ -1,10 +1,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { - IMAGE_LIMIT, - imageSelected, -} from 'features/gallery/store/gallerySlice'; +import { imageSelected } from 'features/gallery/store/gallerySlice'; import { clamp, isEqual } from 'lodash-es'; import { useCallback } from 'react'; import { @@ -14,6 +11,7 @@ import { useLazyListImagesQuery, } from 'services/api/endpoints/images'; import { selectListImagesBaseQueryArgs } from '../store/gallerySelectors'; +import { IMAGE_LIMIT } from '../store/types'; export const nextPrevImageButtonsSelector = createSelector( [stateSelector, selectListImagesBaseQueryArgs], diff --git a/invokeai/frontend/web/src/features/gallery/store/boardSlice.ts b/invokeai/frontend/web/src/features/gallery/store/boardSlice.ts index e6b59eee9a..ad43498e51 100644 --- a/invokeai/frontend/web/src/features/gallery/store/boardSlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/boardSlice.ts @@ -1,5 +1,4 @@ import { PayloadAction, createSlice } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; type BoardsState = { searchText: string; @@ -27,6 +26,4 @@ const boardsSlice = createSlice({ export const { setBoardSearchText, setUpdateBoardModalOpen } = boardsSlice.actions; -export const boardsSelector = (state: RootState) => state.boards; - export default boardsSlice.reducer; diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts index db520c2f35..b589550157 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySelectors.ts @@ -6,7 +6,7 @@ import { ASSETS_CATEGORIES, IMAGE_CATEGORIES, INITIAL_IMAGE_LIMIT, -} from './gallerySlice'; +} from './types'; export const gallerySelector = (state: RootState) => state.gallery; diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index b754018c1f..125463ba94 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -2,32 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice, isAnyOf } from '@reduxjs/toolkit'; import { uniq } from 'lodash-es'; import { boardsApi } from 'services/api/endpoints/boards'; -import { ImageCategory } from 'services/api/types'; - -export const IMAGE_CATEGORIES: ImageCategory[] = ['general']; -export const ASSETS_CATEGORIES: ImageCategory[] = [ - 'control', - 'mask', - 'user', - 'other', -]; -export const INITIAL_IMAGE_LIMIT = 100; -export const IMAGE_LIMIT = 20; - -export type GalleryView = 'images' | 'assets'; -// export type BoardId = 'no_board' | (string & Record); -export type BoardId = string | undefined; - -type GalleryState = { - selection: string[]; - shouldAutoSwitch: boolean; - autoAddBoardId: string | undefined; - galleryImageMinimumWidth: number; - selectedBoardId: BoardId; - galleryView: GalleryView; - batchImageNames: string[]; - isBatchEnabled: boolean; -}; +import { BoardId, GalleryState, GalleryView } from './types'; export const initialGalleryState: GalleryState = { selection: [], diff --git a/invokeai/frontend/web/src/features/gallery/store/types.ts b/invokeai/frontend/web/src/features/gallery/store/types.ts new file mode 100644 index 0000000000..d19a6fded3 --- /dev/null +++ b/invokeai/frontend/web/src/features/gallery/store/types.ts @@ -0,0 +1,26 @@ +import { ImageCategory } from 'services/api/types'; + +export const IMAGE_CATEGORIES: ImageCategory[] = ['general']; +export const ASSETS_CATEGORIES: ImageCategory[] = [ + 'control', + 'mask', + 'user', + 'other', +]; +export const INITIAL_IMAGE_LIMIT = 100; +export const IMAGE_LIMIT = 20; + +export type GalleryView = 'images' | 'assets'; +// export type BoardId = 'no_board' | (string & Record); +export type BoardId = string | undefined; + +export type GalleryState = { + selection: string[]; + shouldAutoSwitch: boolean; + autoAddBoardId: string | undefined; + galleryImageMinimumWidth: number; + selectedBoardId: BoardId; + galleryView: GalleryView; + batchImageNames: string[]; + isBatchEnabled: boolean; +}; diff --git a/invokeai/frontend/web/src/features/gallery/store/util.ts b/invokeai/frontend/web/src/features/gallery/store/util.ts deleted file mode 100644 index 3df5b2af31..0000000000 --- a/invokeai/frontend/web/src/features/gallery/store/util.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { isEqual } from 'lodash-es'; -import { ImageCategory, ImageDTO } from 'services/api/types'; -import { ASSETS_CATEGORIES, BoardId, IMAGE_CATEGORIES } from './gallerySlice'; - -export const getCategoriesQueryParamForBoard = ( - board_id: BoardId -): ImageCategory[] | undefined => { - if (board_id === 'assets') { - return ASSETS_CATEGORIES; - } - - if (board_id === 'images') { - return IMAGE_CATEGORIES; - } - - // 'no_board' board, 'batch' board, user boards - return undefined; -}; - -export const getBoardIdQueryParamForBoard = ( - board_id: BoardId -): string | null => { - if (board_id === undefined) { - return 'none'; - } - - // user boards - return board_id; -}; - -export const getBoardIdFromBoardAndCategoriesQueryParam = ( - board_id: string | undefined, - categories: ImageCategory[] | undefined -): BoardId => { - if (board_id === undefined && isEqual(categories, IMAGE_CATEGORIES)) { - return 'images'; - } - - if (board_id === undefined && isEqual(categories, ASSETS_CATEGORIES)) { - return 'assets'; - } - - if (board_id === 'none') { - return 'no_board'; - } - - return board_id ?? 'UNKNOWN_BOARD'; -}; - -export const getCategories = (imageDTO: ImageDTO) => { - if (IMAGE_CATEGORIES.includes(imageDTO.image_category)) { - return IMAGE_CATEGORIES; - } - return ASSETS_CATEGORIES; -}; diff --git a/invokeai/frontend/web/src/features/imageDeletion/components/DeleteImageModal.tsx b/invokeai/frontend/web/src/features/imageDeletion/components/DeleteImageModal.tsx index 8306437cc7..0e72ea96ad 100644 --- a/invokeai/frontend/web/src/features/imageDeletion/components/DeleteImageModal.tsx +++ b/invokeai/frontend/web/src/features/imageDeletion/components/DeleteImageModal.tsx @@ -16,16 +16,16 @@ import IAIButton from 'common/components/IAIButton'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldConfirmOnDelete } from 'features/system/store/systemSlice'; +import { stateSelector } from 'app/store/store'; import { ChangeEvent, memo, useCallback, useRef } from 'react'; import { useTranslation } from 'react-i18next'; -import ImageUsageMessage from './ImageUsageMessage'; -import { stateSelector } from 'app/store/store'; +import { imageDeletionConfirmed } from '../store/actions'; +import { selectImageUsage } from '../store/imageDeletionSelectors'; import { - imageDeletionConfirmed, imageToDeleteCleared, isModalOpenChanged, - selectImageUsage, } from '../store/imageDeletionSlice'; +import ImageUsageMessage from './ImageUsageMessage'; const selector = createSelector( [stateSelector, selectImageUsage], diff --git a/invokeai/frontend/web/src/features/imageDeletion/components/ImageUsageMessage.tsx b/invokeai/frontend/web/src/features/imageDeletion/components/ImageUsageMessage.tsx index 64d001f8ba..3ed7f3f05f 100644 --- a/invokeai/frontend/web/src/features/imageDeletion/components/ImageUsageMessage.tsx +++ b/invokeai/frontend/web/src/features/imageDeletion/components/ImageUsageMessage.tsx @@ -1,7 +1,7 @@ +import { ListItem, Text, UnorderedList } from '@chakra-ui/react'; import { some } from 'lodash-es'; import { memo } from 'react'; -import { ImageUsage } from '../store/imageDeletionSlice'; -import { ListItem, Text, UnorderedList } from '@chakra-ui/react'; +import { ImageUsage } from '../store/types'; type Props = { imageUsage?: ImageUsage; topMessage?: string; diff --git a/invokeai/frontend/web/src/features/imageDeletion/store/actions.ts b/invokeai/frontend/web/src/features/imageDeletion/store/actions.ts new file mode 100644 index 0000000000..c67d7d944d --- /dev/null +++ b/invokeai/frontend/web/src/features/imageDeletion/store/actions.ts @@ -0,0 +1,8 @@ +import { createAction } from '@reduxjs/toolkit'; +import { ImageDTO } from 'services/api/types'; +import { ImageUsage } from './types'; + +export const imageDeletionConfirmed = createAction<{ + imageDTO: ImageDTO; + imageUsage: ImageUsage; +}>('imageDeletion/imageDeletionConfirmed'); diff --git a/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSelectors.ts b/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSelectors.ts new file mode 100644 index 0000000000..bd8e117496 --- /dev/null +++ b/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSelectors.ts @@ -0,0 +1,55 @@ +import { createSelector } from '@reduxjs/toolkit'; +import { RootState } from 'app/store/store'; +import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; +import { some } from 'lodash-es'; +import { ImageUsage } from './types'; + +export const getImageUsage = (state: RootState, image_name: string) => { + const { generation, canvas, nodes, controlNet } = state; + const isInitialImage = generation.initialImage?.imageName === image_name; + + const isCanvasImage = canvas.layerState.objects.some( + (obj) => obj.kind === 'image' && obj.imageName === image_name + ); + + const isNodesImage = nodes.nodes.some((node) => { + return some( + node.data.inputs, + (input) => + input.type === 'image' && input.value?.image_name === image_name + ); + }); + + const isControlNetImage = some( + controlNet.controlNets, + (c) => + c.controlImage === image_name || c.processedControlImage === image_name + ); + + const imageUsage: ImageUsage = { + isInitialImage, + isCanvasImage, + isNodesImage, + isControlNetImage, + }; + + return imageUsage; +}; + +export const selectImageUsage = createSelector( + [(state: RootState) => state], + (state) => { + const { imageToDelete } = state.imageDeletion; + + if (!imageToDelete) { + return; + } + + const { image_name } = imageToDelete; + + const imageUsage = getImageUsage(state, image_name); + + return imageUsage; + }, + defaultSelectorOptions +); diff --git a/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSlice.ts b/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSlice.ts index df90da5088..0bfd9a537d 100644 --- a/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSlice.ts +++ b/invokeai/frontend/web/src/features/imageDeletion/store/imageDeletionSlice.ts @@ -1,12 +1,4 @@ -import { - PayloadAction, - createAction, - createSelector, - createSlice, -} from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { some } from 'lodash-es'; +import { PayloadAction, createSlice } from '@reduxjs/toolkit'; import { ImageDTO } from 'services/api/types'; type DeleteImageState = { @@ -43,65 +35,3 @@ export const { } = imageDeletion.actions; export default imageDeletion.reducer; - -export type ImageUsage = { - isInitialImage: boolean; - isCanvasImage: boolean; - isNodesImage: boolean; - isControlNetImage: boolean; -}; - -export const getImageUsage = (state: RootState, image_name: string) => { - const { generation, canvas, nodes, controlNet } = state; - const isInitialImage = generation.initialImage?.imageName === image_name; - - const isCanvasImage = canvas.layerState.objects.some( - (obj) => obj.kind === 'image' && obj.imageName === image_name - ); - - const isNodesImage = nodes.nodes.some((node) => { - return some( - node.data.inputs, - (input) => - input.type === 'image' && input.value?.image_name === image_name - ); - }); - - const isControlNetImage = some( - controlNet.controlNets, - (c) => - c.controlImage === image_name || c.processedControlImage === image_name - ); - - const imageUsage: ImageUsage = { - isInitialImage, - isCanvasImage, - isNodesImage, - isControlNetImage, - }; - - return imageUsage; -}; - -export const selectImageUsage = createSelector( - [(state: RootState) => state], - (state) => { - const { imageToDelete } = state.imageDeletion; - - if (!imageToDelete) { - return; - } - - const { image_name } = imageToDelete; - - const imageUsage = getImageUsage(state, image_name); - - return imageUsage; - }, - defaultSelectorOptions -); - -export const imageDeletionConfirmed = createAction<{ - imageDTO: ImageDTO; - imageUsage: ImageUsage; -}>('imageDeletion/imageDeletionConfirmed'); diff --git a/invokeai/frontend/web/src/features/imageDeletion/store/types.ts b/invokeai/frontend/web/src/features/imageDeletion/store/types.ts new file mode 100644 index 0000000000..b3f4dc9c8d --- /dev/null +++ b/invokeai/frontend/web/src/features/imageDeletion/store/types.ts @@ -0,0 +1,6 @@ +export type ImageUsage = { + isInitialImage: boolean; + isCanvasImage: boolean; + isNodesImage: boolean; + isControlNetImage: boolean; +}; diff --git a/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx b/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx index 408bf74eed..a1a1acf1f8 100644 --- a/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/AddNodeMenu.tsx @@ -1,6 +1,7 @@ import { Flex, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppToaster } from 'app/components/Toaster'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect'; @@ -9,7 +10,7 @@ import { forwardRef, useCallback } from 'react'; import 'reactflow/dist/style.css'; import { AnyInvocationType } from 'services/events/types'; import { useBuildInvocation } from '../hooks/useBuildInvocation'; -import { nodeAdded, nodesSelector } from '../store/nodesSlice'; +import { nodeAdded } from '../store/nodesSlice'; type NodeTemplate = { label: string; @@ -18,8 +19,8 @@ type NodeTemplate = { }; const selector = createSelector( - nodesSelector, - (nodes) => { + [stateSelector], + ({ nodes }) => { const data: NodeTemplate[] = map(nodes.invocationTemplates, (template) => { return { label: template.title, diff --git a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeResizer.tsx b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeResizer.tsx index 1217540827..1aca32ec70 100644 --- a/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeResizer.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/IAINode/IAINodeResizer.tsx @@ -1,4 +1,4 @@ -import { NODE_MIN_WIDTH } from 'app/constants'; +import { NODE_MIN_WIDTH } from 'features/nodes/types/constants'; import { memo } from 'react'; import { NodeResizeControl, NodeResizerProps } from 'reactflow'; diff --git a/invokeai/frontend/web/src/features/nodes/components/NodeWrapper.tsx b/invokeai/frontend/web/src/features/nodes/components/NodeWrapper.tsx index 882c6efd69..bc7944a28b 100644 --- a/invokeai/frontend/web/src/features/nodes/components/NodeWrapper.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/NodeWrapper.tsx @@ -1,9 +1,8 @@ import { Box, useToken } from '@chakra-ui/react'; -import { NODE_MIN_WIDTH } from 'app/constants'; - import { useAppSelector } from 'app/store/storeHooks'; import { PropsWithChildren } from 'react'; import { DRAG_HANDLE_CLASSNAME } from '../hooks/useBuildInvocation'; +import { NODE_MIN_WIDTH } from '../types/constants'; type NodeWrapperProps = PropsWithChildren & { selected: boolean; diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx index c5de45a826..86d9d08a84 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/ClearNodesButton.tsx @@ -9,7 +9,7 @@ import { Text, useDisclosure, } from '@chakra-ui/react'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; diff --git a/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx b/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx index 10aecc9fcc..706fbd8b31 100644 --- a/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/ui/LoadNodesButton.tsx @@ -1,5 +1,5 @@ import { FileButton } from '@mantine/core'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIIconButton from 'common/components/IAIIconButton'; import { loadFileEdges, loadFileNodes } from 'features/nodes/store/nodesSlice'; diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesPersistDenylist.ts b/invokeai/frontend/web/src/features/nodes/store/nodesPersistDenylist.ts index ba5c120dae..5cbc3c381d 100644 --- a/invokeai/frontend/web/src/features/nodes/store/nodesPersistDenylist.ts +++ b/invokeai/frontend/web/src/features/nodes/store/nodesPersistDenylist.ts @@ -1,4 +1,4 @@ -import { NodesState } from './nodesSlice'; +import { NodesState } from './types'; /** * Nodes slice persist denylist diff --git a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts index 997d0493dd..436396fb38 100644 --- a/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts +++ b/invokeai/frontend/web/src/features/nodes/store/nodesSlice.ts @@ -1,5 +1,4 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; import { ControlNetModelParam, LoRAModelParam, @@ -7,7 +6,6 @@ import { VaeModelParam, } from 'features/parameters/types/parameterSchemas'; import { cloneDeep, uniqBy } from 'lodash-es'; -import { OpenAPIV3 } from 'openapi-types'; import { RgbaColor } from 'react-colorful'; import { addEdge, @@ -19,24 +17,11 @@ import { Node, NodeChange, OnConnectStartParams, - ReactFlowInstance, } from 'reactflow'; import { receivedOpenAPISchema } from 'services/api/thunks/schema'; import { ImageField } from 'services/api/types'; import { InvocationTemplate, InvocationValue } from '../types/types'; - -export type NodesState = { - nodes: Node[]; - edges: Edge[]; - schema: OpenAPIV3.Document | null; - invocationTemplates: Record; - connectionStartParams: OnConnectStartParams | null; - shouldShowGraphOverlay: boolean; - shouldShowFieldTypeLegend: boolean; - shouldShowMinimapPanel: boolean; - editorInstance: ReactFlowInstance | undefined; - progressNodeSize: { width: number; height: number }; -}; +import { NodesState } from './types'; export const initialNodesState: NodesState = { nodes: [], @@ -194,5 +179,3 @@ export const { } = nodesSlice.actions; export default nodesSlice.reducer; - -export const nodesSelector = (state: RootState) => state.nodes; diff --git a/invokeai/frontend/web/src/features/nodes/store/types.ts b/invokeai/frontend/web/src/features/nodes/store/types.ts new file mode 100644 index 0000000000..14cb92006b --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/store/types.ts @@ -0,0 +1,16 @@ +import { OpenAPIV3 } from 'openapi-types'; +import { Edge, Node, OnConnectStartParams, ReactFlowInstance } from 'reactflow'; +import { InvocationTemplate, InvocationValue } from '../types/types'; + +export type NodesState = { + nodes: Node[]; + edges: Edge[]; + schema: OpenAPIV3.Document | null; + invocationTemplates: Record; + connectionStartParams: OnConnectStartParams | null; + shouldShowGraphOverlay: boolean; + shouldShowFieldTypeLegend: boolean; + shouldShowMinimapPanel: boolean; + editorInstance: ReactFlowInstance | undefined; + progressNodeSize: { width: number; height: number }; +}; diff --git a/invokeai/frontend/web/src/features/nodes/types/constants.ts b/invokeai/frontend/web/src/features/nodes/types/constants.ts index 3a70e52ee5..c07efc9c27 100644 --- a/invokeai/frontend/web/src/features/nodes/types/constants.ts +++ b/invokeai/frontend/web/src/features/nodes/types/constants.ts @@ -157,3 +157,5 @@ export const FIELDS: Record = { description: 'A RGBA color.', }, }; + +export const NODE_MIN_WIDTH = 250; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx index ab44bda16b..66c76ae7cb 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse.tsx @@ -20,7 +20,7 @@ const selector = createSelector( export default function ParamAdvancedCollapse() { const { activeLabel } = useAppSelector(selector); const shouldShowAdvancedOptions = useAppSelector( - (state: RootState) => state.ui.shouldShowAdvancedOptions + (state: RootState) => state.generation.shouldShowAdvancedOptions ); if (!shouldShowAdvancedOptions) { diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx index a2162e6c9d..f51e42b6a1 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Advanced/ParamClipSkip.tsx @@ -2,28 +2,10 @@ import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; import { setClipSkip } from 'features/parameters/store/generationSlice'; +import { clipSkipMap } from 'features/parameters/types/constants'; import { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -export const clipSkipMap = { - 'sd-1': { - maxClip: 12, - markers: [0, 1, 2, 3, 4, 8, 12], - }, - 'sd-2': { - maxClip: 24, - markers: [0, 1, 2, 3, 5, 10, 15, 20, 24], - }, - sdxl: { - maxClip: 24, - markers: [0, 1, 2, 3, 5, 10, 15, 20, 24], - }, - 'sdxl-refiner': { - maxClip: 24, - markers: [0, 1, 2, 3, 5, 10, 15, 20, 24], - }, -}; - export default function ParamClipSkip() { const clipSkip = useAppSelector( (state: RootState) => state.generation.clipSkip diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxHeight.tsx index 12fc4abcf7..64e44e63d0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxHeight.tsx @@ -1,23 +1,20 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider from 'common/components/IAISlider'; import { roundToMultiple } from 'common/util/roundDownToMultiple'; -import { - canvasSelector, - isStagingSelector, -} from 'features/canvas/store/canvasSelectors'; +import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [canvasSelector, isStagingSelector, uiSelector], - (canvas, isStaging, ui) => { + [stateSelector, isStagingSelector], + ({ canvas, generation }, isStaging) => { const { boundingBoxDimensions } = canvas; - const { aspectRatio } = ui; + const { aspectRatio } = generation; return { boundingBoxDimensions, isStaging, diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxWidth.tsx index 5c9a82110a..d5671fb0c0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxWidth.tsx @@ -1,23 +1,20 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider from 'common/components/IAISlider'; import { roundToMultiple } from 'common/util/roundDownToMultiple'; -import { - canvasSelector, - isStagingSelector, -} from 'features/canvas/store/canvasSelectors'; +import { isStagingSelector } from 'features/canvas/store/canvasSelectors'; import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [canvasSelector, isStagingSelector, uiSelector], - (canvas, isStaging, ui) => { + [stateSelector, isStagingSelector], + ({ canvas, generation }, isStaging) => { const { boundingBoxDimensions } = canvas; - const { aspectRatio } = ui; + const { aspectRatio } = generation; return { boundingBoxDimensions, isStaging, diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx index 7f62c8b6c8..99ab512948 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx @@ -1,5 +1,6 @@ import { Divider, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAICollapse from 'common/components/IAICollapse'; @@ -9,7 +10,6 @@ import ParamControlNetFeatureToggle from 'features/controlNet/components/paramet import { controlNetAdded, controlNetModelChanged, - controlNetSelector, } from 'features/controlNet/store/controlNetSlice'; import { getValidControlNets } from 'features/controlNet/util/getValidControlNets'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; @@ -21,8 +21,8 @@ import { useGetControlNetModelsQuery } from 'services/api/endpoints/models'; import { v4 as uuidv4 } from 'uuid'; const selector = createSelector( - controlNetSelector, - (controlNet) => { + [stateSelector], + ({ controlNet }) => { const { controlNets, isEnabled } = controlNet; const validControlNets = getValidControlNets(controlNets); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx index e0bce7254e..657034e362 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx @@ -2,7 +2,7 @@ import { ButtonGroup, Flex } from '@chakra-ui/react'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; -import { setAspectRatio } from 'features/ui/store/uiSlice'; +import { setAspectRatio } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from '../../../../ui/store/uiSelectors'; const aspectRatios = [ @@ -14,7 +14,7 @@ const aspectRatios = [ export default function ParamAspectRatio() { const aspectRatio = useAppSelector( - (state: RootState) => state.ui.aspectRatio + (state: RootState) => state.generation.aspectRatio ); const dispatch = useAppDispatch(); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx index d32ff960d5..54a7ccbe65 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamCFGScale.tsx @@ -1,19 +1,16 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAINumberInput from 'common/components/IAINumberInput'; import IAISlider from 'common/components/IAISlider'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setCfgScale } from 'features/parameters/store/generationSlice'; -import { configSelector } from 'features/system/store/configSelectors'; -import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [generationSelector, configSelector, uiSelector, hotkeysSelector], - (generation, config, ui, hotkeys) => { + [stateSelector], + ({ generation, config, ui, hotkeys }) => { const { initial, min, sliderMax, inputMax } = config.sd.guidance; const { cfgScale } = generation; const { shouldUseSliders } = ui; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx index 63abe0ddf9..37ed43ddc0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx @@ -1,23 +1,20 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider, { IAIFullSliderProps } from 'common/components/IAISlider'; import { roundToMultiple } from 'common/util/roundDownToMultiple'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; -import { configSelector } from 'features/system/store/configSelectors'; -import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [generationSelector, hotkeysSelector, configSelector, uiSelector], - (generation, hotkeys, config, ui) => { + [stateSelector], + ({ generation, hotkeys, config }) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.height; const { height } = generation; - const { aspectRatio } = ui; + const { aspectRatio } = generation; const step = hotkeys.shift ? fineStep : coarseStep; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx index 5be09a2ff5..da1b359b37 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamScheduler.tsx @@ -1,12 +1,15 @@ import { createSelector } from '@reduxjs/toolkit'; -import { SCHEDULER_LABEL_MAP, SCHEDULER_NAMES } from 'app/constants'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAIMantineSearchableSelect from 'common/components/IAIMantineSearchableSelect'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setScheduler } from 'features/parameters/store/generationSlice'; -import { SchedulerParam } from 'features/parameters/types/parameterSchemas'; +import { + SCHEDULER_LABEL_MAP, + SchedulerParam, +} from 'features/parameters/types/parameterSchemas'; import { uiSelector } from 'features/ui/store/uiSelectors'; +import { map } from 'lodash-es'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; @@ -16,10 +19,10 @@ const selector = createSelector( const { scheduler } = generation; const { favoriteSchedulers: enabledSchedulers } = ui; - const data = SCHEDULER_NAMES.map((schedulerName) => ({ - value: schedulerName, - label: SCHEDULER_LABEL_MAP[schedulerName as SchedulerParam], - group: enabledSchedulers.includes(schedulerName) + const data = map(SCHEDULER_LABEL_MAP, (label, name) => ({ + value: name, + label: label, + group: enabledSchedulers.includes(name as SchedulerParam) ? 'Favorites' : undefined, })).sort((a, b) => a.label.localeCompare(b.label)); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSteps.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSteps.tsx index d939113c7c..3728e59158 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSteps.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSteps.tsx @@ -1,23 +1,20 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAINumberInput from 'common/components/IAINumberInput'; import IAISlider from 'common/components/IAISlider'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; import { clampSymmetrySteps, setSteps, } from 'features/parameters/store/generationSlice'; -import { configSelector } from 'features/system/store/configSelectors'; -import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [generationSelector, configSelector, uiSelector, hotkeysSelector], - (generation, config, ui, hotkeys) => { + [stateSelector], + ({ generation, config, ui, hotkeys }) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.steps; const { steps } = generation; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx index 991db19097..55daadf9ea 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx @@ -1,23 +1,19 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider, { IAIFullSliderProps } from 'common/components/IAISlider'; import { roundToMultiple } from 'common/util/roundDownToMultiple'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; -import { configSelector } from 'features/system/store/configSelectors'; -import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [generationSelector, hotkeysSelector, configSelector, uiSelector], - (generation, hotkeys, config, ui) => { + [stateSelector], + ({ generation, hotkeys, config, ui }) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.width; - const { width } = generation; - const { aspectRatio } = ui; + const { width, aspectRatio } = generation; const step = hotkeys.shift ? fineStep : coarseStep; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx index eea5ec3c27..b45fc9f386 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/ImageToImageStrength.tsx @@ -1,17 +1,15 @@ import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider from 'common/components/IAISlider'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setImg2imgStrength } from 'features/parameters/store/generationSlice'; -import { configSelector } from 'features/system/store/configSelectors'; -import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; const selector = createSelector( - [generationSelector, hotkeysSelector, configSelector], - (generation, hotkeys, config) => { + [stateSelector], + ({ generation, hotkeys, config }) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.img2imgStrength; const { img2imgStrength } = generation; diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index c5ec7930a4..9a1d514a49 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -1,15 +1,10 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import { DEFAULT_SCHEDULER_NAME } from 'app/constants'; import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { configChanged } from 'features/system/store/configSlice'; -import { - setAspectRatio, - setShouldShowAdvancedOptions, -} from 'features/ui/store/uiSlice'; import { clamp } from 'lodash-es'; import { ImageDTO, MainModelField } from 'services/api/types'; -import { clipSkipMap } from '../components/Parameters/Advanced/ParamClipSkip'; +import { clipSkipMap } from '../types/constants'; import { CfgScaleParam, HeightParam, @@ -60,6 +55,8 @@ export interface GenerationState { seamlessYAxis: boolean; clipSkip: number; shouldUseCpuNoise: boolean; + shouldShowAdvancedOptions: boolean; + aspectRatio: number | null; } export const initialGenerationState: GenerationState = { @@ -71,7 +68,7 @@ export const initialGenerationState: GenerationState = { perlin: 0, positivePrompt: '', negativePrompt: '', - scheduler: DEFAULT_SCHEDULER_NAME, + scheduler: 'euler', seamBlur: 16, seamSize: 96, seamSteps: 30, @@ -96,6 +93,8 @@ export const initialGenerationState: GenerationState = { seamlessYAxis: false, clipSkip: 0, shouldUseCpuNoise: true, + shouldShowAdvancedOptions: false, + aspectRatio: null, }; const initialState: GenerationState = initialGenerationState; @@ -248,6 +247,19 @@ export const generationSlice = createSlice({ shouldUseCpuNoiseChanged: (state, action: PayloadAction) => { state.shouldUseCpuNoise = action.payload; }, + setShouldShowAdvancedOptions: (state, action: PayloadAction) => { + state.shouldShowAdvancedOptions = action.payload; + if (!action.payload) { + state.clipSkip = 0; + } + }, + setAspectRatio: (state, action: PayloadAction) => { + const newAspectRatio = action.payload; + state.aspectRatio = newAspectRatio; + if (newAspectRatio) { + state.height = roundToMultiple(state.width / newAspectRatio, 8); + } + }, }, extraReducers: (builder) => { builder.addCase(configChanged, (state, action) => { @@ -270,12 +282,6 @@ export const generationSlice = createSlice({ const advancedOptionsStatus = action.payload; if (!advancedOptionsStatus) state.clipSkip = 0; }); - builder.addCase(setAspectRatio, (state, action) => { - const ratio = action.payload; - if (ratio) { - state.height = roundToMultiple(state.width / ratio, 8); - } - }); }, }); @@ -319,6 +325,8 @@ export const { setSeamlessYAxis, setClipSkip, shouldUseCpuNoiseChanged, + setShouldShowAdvancedOptions, + setAspectRatio, } = generationSlice.actions; export default generationSlice.reducer; diff --git a/invokeai/frontend/web/src/features/parameters/types/constants.ts b/invokeai/frontend/web/src/features/parameters/types/constants.ts index 04917646d1..ca52bfb95a 100644 --- a/invokeai/frontend/web/src/features/parameters/types/constants.ts +++ b/invokeai/frontend/web/src/features/parameters/types/constants.ts @@ -4,3 +4,22 @@ export const MODEL_TYPE_MAP = { sdxl: 'Stable Diffusion XL', 'sdxl-refiner': 'Stable Diffusion XL Refiner', }; + +export const clipSkipMap = { + 'sd-1': { + maxClip: 12, + markers: [0, 1, 2, 3, 4, 8, 12], + }, + 'sd-2': { + maxClip: 24, + markers: [0, 1, 2, 3, 5, 10, 15, 20, 24], + }, + sdxl: { + maxClip: 24, + markers: [0, 1, 2, 3, 5, 10, 15, 20, 24], + }, + 'sdxl-refiner': { + maxClip: 24, + markers: [0, 1, 2, 3, 5, 10, 15, 20, 24], + }, +}; diff --git a/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts b/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts index c2b6eb6187..cea5fb9987 100644 --- a/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts +++ b/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts @@ -1,4 +1,4 @@ -import { NUMPY_RAND_MAX, SCHEDULER_NAMES_AS_CONST } from 'app/constants'; +import { NUMPY_RAND_MAX } from 'app/constants'; import { z } from 'zod'; /** @@ -73,7 +73,30 @@ export const isValidCfgScale = (val: unknown): val is CfgScaleParam => /** * Zod schema for scheduler parameter */ -export const zScheduler = z.enum(SCHEDULER_NAMES_AS_CONST); +export const zScheduler = z.enum([ + 'euler', + 'deis', + 'ddim', + 'ddpm', + 'dpmpp_2s', + 'dpmpp_2m', + 'dpmpp_2m_sde', + 'dpmpp_sde', + 'heun', + 'kdpm_2', + 'lms', + 'pndm', + 'unipc', + 'euler_k', + 'dpmpp_2s_k', + 'dpmpp_2m_k', + 'dpmpp_2m_sde_k', + 'dpmpp_sde_k', + 'heun_k', + 'lms_k', + 'euler_a', + 'kdpm_2_a', +]); /** * Type alias for scheduler parameter, inferred from its zod schema */ @@ -84,6 +107,31 @@ export type SchedulerParam = z.infer; export const isValidScheduler = (val: unknown): val is SchedulerParam => zScheduler.safeParse(val).success; +export const SCHEDULER_LABEL_MAP: Record = { + euler: 'Euler', + deis: 'DEIS', + ddim: 'DDIM', + ddpm: 'DDPM', + dpmpp_sde: 'DPM++ SDE', + dpmpp_2s: 'DPM++ 2S', + dpmpp_2m: 'DPM++ 2M', + dpmpp_2m_sde: 'DPM++ 2M SDE', + heun: 'Heun', + kdpm_2: 'KDPM 2', + lms: 'LMS', + pndm: 'PNDM', + unipc: 'UniPC', + euler_k: 'Euler Karras', + dpmpp_sde_k: 'DPM++ SDE Karras', + dpmpp_2s_k: 'DPM++ 2S Karras', + dpmpp_2m_k: 'DPM++ 2M Karras', + dpmpp_2m_sde_k: 'DPM++ 2M SDE Karras', + heun_k: 'Heun Karras', + lms_k: 'LMS Karras', + euler_a: 'Euler Ancestral', + kdpm_2_a: 'KDPM 2 Ancestral', +}; + /** * Zod schema for seed parameter */ diff --git a/invokeai/frontend/web/src/features/system/components/LanguagePicker.tsx b/invokeai/frontend/web/src/features/system/components/LanguagePicker.tsx index 3e4e423c3f..0a88ac9215 100644 --- a/invokeai/frontend/web/src/features/system/components/LanguagePicker.tsx +++ b/invokeai/frontend/web/src/features/system/components/LanguagePicker.tsx @@ -7,32 +7,13 @@ import { MenuOptionGroup, Tooltip, } from '@chakra-ui/react'; -import { useTranslation } from 'react-i18next'; -import i18n from 'i18n'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { map } from 'lodash-es'; +import { useTranslation } from 'react-i18next'; +import { IoLanguage } from 'react-icons/io5'; +import { LANGUAGES } from '../store/constants'; import { languageSelector } from '../store/systemSelectors'; import { languageChanged } from '../store/systemSlice'; -import { map } from 'lodash-es'; -import { IoLanguage } from 'react-icons/io5'; - -export const LANGUAGES = { - ar: i18n.t('common.langArabic', { lng: 'ar' }), - nl: i18n.t('common.langDutch', { lng: 'nl' }), - en: i18n.t('common.langEnglish', { lng: 'en' }), - fr: i18n.t('common.langFrench', { lng: 'fr' }), - de: i18n.t('common.langGerman', { lng: 'de' }), - he: i18n.t('common.langHebrew', { lng: 'he' }), - it: i18n.t('common.langItalian', { lng: 'it' }), - ja: i18n.t('common.langJapanese', { lng: 'ja' }), - ko: i18n.t('common.langKorean', { lng: 'ko' }), - pl: i18n.t('common.langPolish', { lng: 'pl' }), - pt_BR: i18n.t('common.langBrPortuguese', { lng: 'pt_BR' }), - pt: i18n.t('common.langPortuguese', { lng: 'pt' }), - ru: i18n.t('common.langRussian', { lng: 'ru' }), - zh_CN: i18n.t('common.langSimplifiedChinese', { lng: 'zh_CN' }), - es: i18n.t('common.langSpanish', { lng: 'es' }), - uk: i18n.t('common.langUkranian', { lng: 'ua' }), -}; export default function LanguagePicker() { const { t } = useTranslation(); diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx index 9d095f3511..85fbf016b8 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsClearIntermediates.tsx @@ -1,5 +1,6 @@ import { Heading, Text } from '@chakra-ui/react'; import { useAppDispatch } from 'app/store/storeHooks'; +import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; import { useCallback, useEffect } from 'react'; import IAIButton from '../../../../common/components/IAIButton'; import { @@ -8,8 +9,7 @@ import { } from '../../../../services/api/endpoints/images'; import { resetCanvas } from '../../../canvas/store/canvasSlice'; import { addToast } from '../../store/systemSlice'; -import { StyledFlex } from './SettingsModal'; -import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; +import StyledFlex from './StyledFlex'; export default function SettingsClearIntermediates() { const dispatch = useAppDispatch(); diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index 7df4c39cbb..2deccfa46d 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -14,12 +14,12 @@ import { import { createSelector } from '@reduxjs/toolkit'; import { VALID_LOG_LEVELS } from 'app/logging/logger'; import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIMantineSelect from 'common/components/IAIMantineSelect'; -import { systemSelector } from 'features/system/store/systemSelectors'; +import { setShouldShowAdvancedOptions } from 'features/parameters/store/generationSlice'; import { - SystemState, consoleLogLevelChanged, setEnableImageDebugging, setIsNodesEnabled, @@ -27,18 +27,14 @@ import { shouldAntialiasProgressImageChanged, shouldLogToConsoleChanged, } from 'features/system/store/systemSlice'; -import { uiSelector } from 'features/ui/store/uiSelectors'; import { - setShouldShowAdvancedOptions, setShouldShowProgressInViewer, setShouldUseCanvasBetaLayout, setShouldUseSliders, } from 'features/ui/store/uiSlice'; -import { UIState } from 'features/ui/store/uiTypes'; import { isEqual } from 'lodash-es'; import { ChangeEvent, - PropsWithChildren, ReactElement, cloneElement, useCallback, @@ -49,10 +45,11 @@ import { LogLevelName } from 'roarr'; import SettingSwitch from './SettingSwitch'; import SettingsClearIntermediates from './SettingsClearIntermediates'; import SettingsSchedulers from './SettingsSchedulers'; +import StyledFlex from './StyledFlex'; const selector = createSelector( - [systemSelector, uiSelector], - (system: SystemState, ui: UIState) => { + [stateSelector], + ({ system, ui, generation }) => { const { shouldConfirmOnDelete, enableImageDebugging, @@ -66,9 +63,10 @@ const selector = createSelector( shouldUseCanvasBetaLayout, shouldUseSliders, shouldShowProgressInViewer, - shouldShowAdvancedOptions, } = ui; + const { shouldShowAdvancedOptions } = generation; + return { shouldConfirmOnDelete, enableImageDebugging, @@ -349,22 +347,3 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { }; export default SettingsModal; - -export const StyledFlex = (props: PropsWithChildren) => { - return ( - - {props.children} - - ); -}; diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx index 959559548e..6d2e963b6a 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsSchedulers.tsx @@ -1,16 +1,18 @@ -import { SCHEDULER_LABEL_MAP, SCHEDULER_NAMES } from 'app/constants'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIMantineMultiSelect from 'common/components/IAIMantineMultiSelect'; -import { SchedulerParam } from 'features/parameters/types/parameterSchemas'; +import { + SCHEDULER_LABEL_MAP, + SchedulerParam, +} from 'features/parameters/types/parameterSchemas'; import { favoriteSchedulersChanged } from 'features/ui/store/uiSlice'; import { map } from 'lodash-es'; import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -const data = map(SCHEDULER_NAMES, (s) => ({ - value: s, - label: SCHEDULER_LABEL_MAP[s], +const data = map(SCHEDULER_LABEL_MAP, (value, label) => ({ + value, + label, })).sort((a, b) => a.label.localeCompare(b.label)); export default function SettingsSchedulers() { diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/StyledFlex.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/StyledFlex.tsx new file mode 100644 index 0000000000..fd0580f4e2 --- /dev/null +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/StyledFlex.tsx @@ -0,0 +1,23 @@ +import { Flex } from '@chakra-ui/react'; +import { PropsWithChildren } from 'react'; + +const StyledFlex = (props: PropsWithChildren) => { + return ( + + {props.children} + + ); +}; + +export default StyledFlex; diff --git a/invokeai/frontend/web/src/features/system/store/constants.ts b/invokeai/frontend/web/src/features/system/store/constants.ts new file mode 100644 index 0000000000..4e7dd0b9a8 --- /dev/null +++ b/invokeai/frontend/web/src/features/system/store/constants.ts @@ -0,0 +1,20 @@ +import i18n from 'i18n'; + +export const LANGUAGES = { + ar: i18n.t('common.langArabic', { lng: 'ar' }), + nl: i18n.t('common.langDutch', { lng: 'nl' }), + en: i18n.t('common.langEnglish', { lng: 'en' }), + fr: i18n.t('common.langFrench', { lng: 'fr' }), + de: i18n.t('common.langGerman', { lng: 'de' }), + he: i18n.t('common.langHebrew', { lng: 'he' }), + it: i18n.t('common.langItalian', { lng: 'it' }), + ja: i18n.t('common.langJapanese', { lng: 'ja' }), + ko: i18n.t('common.langKorean', { lng: 'ko' }), + pl: i18n.t('common.langPolish', { lng: 'pl' }), + pt_BR: i18n.t('common.langBrPortuguese', { lng: 'pt_BR' }), + pt: i18n.t('common.langPortuguese', { lng: 'pt' }), + ru: i18n.t('common.langRussian', { lng: 'ru' }), + zh_CN: i18n.t('common.langSimplifiedChinese', { lng: 'zh_CN' }), + es: i18n.t('common.langSpanish', { lng: 'es' }), + uk: i18n.t('common.langUkranian', { lng: 'ua' }), +}; diff --git a/invokeai/frontend/web/src/features/system/store/systemSlice.ts b/invokeai/frontend/web/src/features/system/store/systemSlice.ts index aca126bb13..629a4f0139 100644 --- a/invokeai/frontend/web/src/features/system/store/systemSlice.ts +++ b/invokeai/frontend/web/src/features/system/store/systemSlice.ts @@ -1,6 +1,5 @@ import { UseToastOptions } from '@chakra-ui/react'; import { PayloadAction, createSlice } from '@reduxjs/toolkit'; - import { InvokeLogLevel } from 'app/logging/logger'; import { userInvoked } from 'app/store/actions'; import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice'; @@ -22,8 +21,8 @@ import { appSocketUnsubscribed, } from 'services/events/actions'; import { ProgressImage } from 'services/events/types'; -import { makeToast } from '../../../app/components/Toaster'; -import { LANGUAGES } from '../components/LanguagePicker'; +import { makeToast } from '../util/makeToast'; +import { LANGUAGES } from './constants'; export type CancelStrategy = 'immediate' | 'scheduled'; diff --git a/invokeai/frontend/web/src/features/system/util/makeToast.ts b/invokeai/frontend/web/src/features/system/util/makeToast.ts new file mode 100644 index 0000000000..2d5e88bdb7 --- /dev/null +++ b/invokeai/frontend/web/src/features/system/util/makeToast.ts @@ -0,0 +1,20 @@ +import { UseToastOptions } from '@chakra-ui/react'; + +export type MakeToastArg = string | UseToastOptions; + +/** + * Makes a toast from a string or a UseToastOptions object. + * If a string is passed, the toast will have the status 'info' and will be closable with a duration of 2500ms. + */ +export const makeToast = (arg: MakeToastArg): UseToastOptions => { + if (typeof arg === 'string') { + return { + title: arg, + status: 'info', + isClosable: true, + duration: 2500, + }; + } + + return { status: 'info', isClosable: true, duration: 2500, ...arg }; +}; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddCheckpoint.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddCheckpoint.tsx index ededadaa06..fd5106b289 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddCheckpoint.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddCheckpoint.tsx @@ -1,6 +1,6 @@ import { Flex } from '@chakra-ui/react'; import { useForm } from '@mantine/form'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIMantineTextInput from 'common/components/IAIMantineInput'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddDiffusers.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddDiffusers.tsx index ce8da9289b..376631bd1f 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddDiffusers.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/AdvancedAddDiffusers.tsx @@ -1,6 +1,6 @@ import { Flex } from '@chakra-ui/react'; import { useForm } from '@mantine/form'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIMantineTextInput from 'common/components/IAIMantineInput'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx index bcb0e02298..10f297ce07 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/FoundModelsList.tsx @@ -1,5 +1,5 @@ import { Flex, Text } from '@chakra-ui/react'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SimpleAddModels.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SimpleAddModels.tsx index 7811e462dc..cb0ce627a0 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SimpleAddModels.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/AddModelsPanel/SimpleAddModels.tsx @@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'; import { SelectItem } from '@mantine/core'; import { useForm } from '@mantine/form'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { RootState } from 'app/store/store'; import IAIButton from 'common/components/IAIButton'; import IAIMantineTextInput from 'common/components/IAIMantineInput'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx index 6edd0e8d81..19ca10e240 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/MergeModelsPanel.tsx @@ -1,5 +1,5 @@ import { Flex, Radio, RadioGroup, Text, Tooltip } from '@chakra-ui/react'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIInput from 'common/components/IAIInput'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/CheckpointModelEdit.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/CheckpointModelEdit.tsx index 2f2706d640..cb297d3afe 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/CheckpointModelEdit.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/CheckpointModelEdit.tsx @@ -1,6 +1,6 @@ import { Badge, Divider, Flex, Text } from '@chakra-ui/react'; import { useForm } from '@mantine/form'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIMantineTextInput from 'common/components/IAIMantineInput'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/DiffusersModelEdit.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/DiffusersModelEdit.tsx index 37a08959be..39ba4bc4ce 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/DiffusersModelEdit.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/DiffusersModelEdit.tsx @@ -1,6 +1,6 @@ import { Divider, Flex, Text } from '@chakra-ui/react'; import { useForm } from '@mantine/form'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIMantineTextInput from 'common/components/IAIMantineInput'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelConvert.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelConvert.tsx index 741afba025..1aec7d5c05 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelConvert.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelConvert.tsx @@ -7,7 +7,7 @@ import { Tooltip, UnorderedList, } from '@chakra-ui/react'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; // import { convertToDiffusers } from 'app/socketio/actions'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelListItem.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelListItem.tsx index 4de5131f65..7f4fb0c736 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelListItem.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerPanel/ModelListItem.tsx @@ -1,6 +1,6 @@ import { DeleteIcon } from '@chakra-ui/icons'; import { Badge, Flex, Text, Tooltip } from '@chakra-ui/react'; -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIAlertDialog from 'common/components/IAIAlertDialog'; import IAIButton from 'common/components/IAIButton'; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerSettingsPanel/SyncModelsButton.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerSettingsPanel/SyncModelsButton.tsx index e42794c0b4..6405fba1a7 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerSettingsPanel/SyncModelsButton.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ModelManager/subpanels/ModelManagerSettingsPanel/SyncModelsButton.tsx @@ -1,4 +1,4 @@ -import { makeToast } from 'app/components/Toaster'; +import { makeToast } from 'features/system/util/makeToast'; import { useAppDispatch } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import IAIIconButton from 'common/components/IAIIconButton'; diff --git a/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts b/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts index 527e0b1740..2c16d6b5f4 100644 --- a/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/hotkeysSlice.ts @@ -1,6 +1,5 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; type HotkeysState = { shift: boolean; @@ -23,5 +22,3 @@ export const hotkeysSlice = createSlice({ export const { shiftKeyPressed } = hotkeysSlice.actions; export default hotkeysSlice.reducer; - -export const hotkeysSelector = (state: RootState) => state.hotkeys; diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index c653e40368..81243aa03f 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -19,8 +19,6 @@ export const initialUIState: UIState = { shouldHidePreview: false, shouldShowProgressInViewer: true, shouldShowEmbeddingPicker: false, - shouldShowAdvancedOptions: false, - aspectRatio: null, favoriteSchedulers: [], }; @@ -98,12 +96,6 @@ export const uiSlice = createSlice({ toggleEmbeddingPicker: (state) => { state.shouldShowEmbeddingPicker = !state.shouldShowEmbeddingPicker; }, - setShouldShowAdvancedOptions: (state, action: PayloadAction) => { - state.shouldShowAdvancedOptions = action.payload; - }, - setAspectRatio: (state, action: PayloadAction) => { - state.aspectRatio = action.payload; - }, }, extraReducers(builder) { builder.addCase(initialImageChanged, (state) => { @@ -130,8 +122,6 @@ export const { setShouldShowProgressInViewer, favoriteSchedulersChanged, toggleEmbeddingPicker, - setShouldShowAdvancedOptions, - setAspectRatio, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 325e8e898f..71c83b1630 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -25,7 +25,5 @@ export interface UIState { shouldShowGallery: boolean; shouldShowProgressInViewer: boolean; shouldShowEmbeddingPicker: boolean; - shouldShowAdvancedOptions: boolean; - aspectRatio: number | null; favoriteSchedulers: SchedulerParam[]; } diff --git a/invokeai/frontend/web/src/services/api/endpoints/boards.ts b/invokeai/frontend/web/src/services/api/endpoints/boards.ts index 779e5708fe..73b894b492 100644 --- a/invokeai/frontend/web/src/services/api/endpoints/boards.ts +++ b/invokeai/frontend/web/src/services/api/endpoints/boards.ts @@ -2,8 +2,7 @@ import { Update } from '@reduxjs/toolkit'; import { ASSETS_CATEGORIES, IMAGE_CATEGORIES, - boardIdSelected, -} from 'features/gallery/store/gallerySlice'; +} from 'features/gallery/store/types'; import { BoardDTO, ImageDTO, diff --git a/invokeai/frontend/web/src/services/api/endpoints/images.ts b/invokeai/frontend/web/src/services/api/endpoints/images.ts index 56b9e14a88..e8740a418b 100644 --- a/invokeai/frontend/web/src/services/api/endpoints/images.ts +++ b/invokeai/frontend/web/src/services/api/endpoints/images.ts @@ -5,8 +5,7 @@ import { ASSETS_CATEGORIES, BoardId, IMAGE_CATEGORIES, -} from 'features/gallery/store/gallerySlice'; -import { getCategories } from 'features/gallery/store/util'; +} from 'features/gallery/store/types'; import queryString from 'query-string'; import { ApiFullTagDescription, api } from '..'; import { components, paths } from '../schema'; @@ -16,7 +15,37 @@ import { OffsetPaginatedResults_ImageDTO_, PostUploadAction, } from '../types'; -import { getIsImageInDateRange } from './util'; + +const getIsImageInDateRange = ( + data: ImageCache | undefined, + imageDTO: ImageDTO +) => { + if (!data) { + return false; + } + const cacheImageDTOS = imagesSelectors.selectAll(data); + + if (cacheImageDTOS.length > 1) { + // Images are sorted by `created_at` DESC + // check if the image is newer than the oldest image in the cache + const createdDate = new Date(imageDTO.created_at); + const oldestDate = new Date( + cacheImageDTOS[cacheImageDTOS.length - 1].created_at + ); + return createdDate >= oldestDate; + } else if ([0, 1].includes(cacheImageDTOS.length)) { + // if there are only 1 or 0 images in the cache, we consider the image to be in the date range + return true; + } + return false; +}; + +const getCategories = (imageDTO: ImageDTO) => { + if (IMAGE_CATEGORIES.includes(imageDTO.image_category)) { + return IMAGE_CATEGORIES; + } + return ASSETS_CATEGORIES; +}; export type ListImagesArgs = NonNullable< paths['/api/v1/images/']['get']['parameters']['query'] diff --git a/invokeai/frontend/web/src/services/api/endpoints/util.ts b/invokeai/frontend/web/src/services/api/endpoints/util.ts deleted file mode 100644 index 0172c1af44..0000000000 --- a/invokeai/frontend/web/src/services/api/endpoints/util.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { ImageDTO } from '../types'; -import { ImageCache, imagesSelectors } from './images'; - -export const getIsImageInDateRange = ( - data: ImageCache | undefined, - imageDTO: ImageDTO -) => { - if (!data) { - return false; - } - const cacheImageDTOS = imagesSelectors.selectAll(data); - - if (cacheImageDTOS.length > 1) { - // Images are sorted by `created_at` DESC - // check if the image is newer than the oldest image in the cache - const createdDate = new Date(imageDTO.created_at); - const oldestDate = new Date( - cacheImageDTOS[cacheImageDTOS.length - 1].created_at - ); - return createdDate >= oldestDate; - } else if ([0, 1].includes(cacheImageDTOS.length)) { - // if there are only 1 or 0 images in the cache, we consider the image to be in the date range - return true; - } - return false; -}; - -// /** -// * Determines the action we should take when an image may need to be added or updated in a cache. -// */ -// export const getCacheAction = ( -// data: ImageCache | undefined, -// imageDTO: ImageDTO -// ): 'add' | 'update' | 'none' => { -// const isInDateRange = getIsImageInDateRange(data, imageDTO); -// const isCacheFullyPopulated = data && data.total === data.ids.length; -// const shouldUpdateCache = -// Boolean(isInDateRange) || Boolean(isCacheFullyPopulated); - -// const isImageInCache = data && data.ids.includes(imageDTO.image_name); - -// if (shouldUpdateCache && isImageInCache) { -// return 'update'; -// } - -// if (shouldUpdateCache && !isImageInCache) { -// return 'add'; -// } - -// return 'none'; -// }; diff --git a/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts b/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts index d6b010e3ab..748f2c8f6e 100644 --- a/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts +++ b/invokeai/frontend/web/src/services/api/hooks/useBoardName.ts @@ -1,4 +1,4 @@ -import { BoardId } from 'features/gallery/store/gallerySlice'; +import { BoardId } from 'features/gallery/store/types'; import { useListAllBoardsQuery } from '../endpoints/boards'; export const useBoardName = (board_id: BoardId | null | undefined) => { diff --git a/invokeai/frontend/web/src/services/api/hooks/useBoardTotal.ts b/invokeai/frontend/web/src/services/api/hooks/useBoardTotal.ts index 1a9e69ff2d..dd144ffe00 100644 --- a/invokeai/frontend/web/src/services/api/hooks/useBoardTotal.ts +++ b/invokeai/frontend/web/src/services/api/hooks/useBoardTotal.ts @@ -1,5 +1,5 @@ import { useAppSelector } from 'app/store/storeHooks'; -import { BoardId } from 'features/gallery/store/gallerySlice'; +import { BoardId } from 'features/gallery/store/types'; import { useMemo } from 'react'; import { useGetBoardAssetsTotalQuery, diff --git a/invokeai/frontend/web/src/services/api/thunks/session.ts b/invokeai/frontend/web/src/services/api/thunks/session.ts index 1b4be92bc3..6d20b9dd33 100644 --- a/invokeai/frontend/web/src/services/api/thunks/session.ts +++ b/invokeai/frontend/web/src/services/api/thunks/session.ts @@ -1,5 +1,4 @@ -import { isAnyOf } from '@reduxjs/toolkit'; -import { createAppAsyncThunk } from 'app/store/storeUtils'; +import { createAsyncThunk, isAnyOf } from '@reduxjs/toolkit'; import { isObject } from 'lodash-es'; import { $client } from 'services/api/client'; import { paths } from 'services/api/schema'; @@ -25,7 +24,7 @@ type CreateSessionThunkConfig = { /** * `SessionsService.createSession()` thunk */ -export const sessionCreated = createAppAsyncThunk< +export const sessionCreated = createAsyncThunk< CreateSessionResponse, CreateSessionArg, CreateSessionThunkConfig @@ -63,7 +62,7 @@ const isErrorWithStatus = (error: unknown): error is { status: number } => /** * `SessionsService.invokeSession()` thunk */ -export const sessionInvoked = createAppAsyncThunk< +export const sessionInvoked = createAsyncThunk< InvokedSessionResponse, InvokedSessionArg, InvokedSessionThunkConfig @@ -101,7 +100,7 @@ type CancelSessionThunkConfig = { /** * `SessionsService.cancelSession()` thunk */ -export const sessionCanceled = createAppAsyncThunk< +export const sessionCanceled = createAsyncThunk< CancelSessionResponse, CancelSessionArg, CancelSessionThunkConfig @@ -141,7 +140,7 @@ type ListSessionsThunkConfig = { /** * `SessionsService.listSessions()` thunk */ -export const listedSessions = createAppAsyncThunk< +export const listedSessions = createAsyncThunk< ListSessionsResponse, ListSessionsArg, ListSessionsThunkConfig diff --git a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts index eaa5596e37..a13c128811 100644 --- a/invokeai/frontend/web/src/services/events/util/setEventListeners.ts +++ b/invokeai/frontend/web/src/services/events/util/setEventListeners.ts @@ -1,9 +1,9 @@ import { MiddlewareAPI } from '@reduxjs/toolkit'; import { logger } from 'app/logging/logger'; import { AppDispatch, RootState } from 'app/store/store'; +import { addToast } from 'features/system/store/systemSlice'; +import { makeToast } from 'features/system/util/makeToast'; import { Socket } from 'socket.io-client'; -import { makeToast } from '../../../app/components/Toaster'; -import { addToast } from '../../../features/system/store/systemSlice'; import { socketConnected, socketDisconnected, From c5147d0f57e60893d5fb7eb2694f2e6240e0628d Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sat, 22 Jul 2023 23:26:14 +1000 Subject: [PATCH 4/4] fix(ui): fix all eslint & prettier issues --- invokeai/frontend/web/.prettierignore | 4 + .../frontend/web/src/app/logging/useLogger.ts | 2 + .../enhancers/reduxRemember/unserialize.ts | 2 +- .../addFirstListImagesListener.ts.ts | 2 +- .../listeners/appStarted.ts | 5 +- .../listeners/boardAndImagesDeleted.ts | 4 +- .../listeners/canvasMerged.ts | 2 +- .../listeners/canvasSavedToGallery.ts | 2 +- .../listeners/controlNetAutoProcess.ts | 5 +- .../listeners/controlNetImageProcessed.ts | 7 +- .../listeners/imageAddedToBoard.ts | 4 +- .../listeners/imageDeleted.ts | 8 +- .../listeners/imageDropped.ts | 2 +- .../listeners/imageRemovedFromBoard.ts | 4 +- .../listeners/imageToDeleteSelected.ts | 2 +- .../listeners/imageUploaded.ts | 11 +- .../listeners/initialImageSelected.ts | 2 +- .../listeners/modelsLoaded.ts | 6 +- .../listeners/receivedOpenAPISchema.ts | 6 +- .../listeners/sessionCanceled.ts | 7 +- .../listeners/sessionCreated.ts | 9 +- .../listeners/sessionInvoked.ts | 9 +- .../listeners/socketio/socketDisconnected.ts | 2 +- .../socketGraphExecutionStateComplete.ts | 2 +- .../socketio/socketInvocationComplete.ts | 2 +- .../socketio/socketInvocationError.ts | 2 +- .../listeners/socketio/socketModelLoad.ts | 13 +- .../listeners/socketio/socketSubscribed.ts | 2 +- .../listeners/socketio/socketUnsubscribed.ts | 2 +- .../listeners/stagingAreaImageSaved.ts | 4 +- .../listeners/upscaleRequested.ts | 5 +- invokeai/frontend/web/src/app/store/store.ts | 2 +- .../src/common/components/IAIDroppable.tsx | 3 +- .../IAIMantineSelectItemWithTooltip.tsx | 5 +- .../web/src/common/components/IAISlider.tsx | 6 +- .../features/canvas/components/IAICanvas.tsx | 4 +- .../src/features/canvas/store/canvasSlice.ts | 26 +-- .../components/ControlNetImagePreview.tsx | 20 +-- .../parameters/ParamControlNetBeginEnd.tsx | 5 - .../parameters/ParamControlNetControlMode.tsx | 3 - .../ParamControlNetProcessorSelect.tsx | 1 - .../parameters/ParamControlNetResizeMode.tsx | 3 - .../processors/ZoeDepthProcessor.tsx | 2 +- .../controlNet/store/controlNetSlice.ts | 4 +- .../components/Boards/BoardContextMenu.tsx | 22 +-- .../Boards/BoardsList/BoardsList.tsx | 10 +- .../Boards/BoardsList/GalleryBoard.tsx | 11 +- .../Boards/BoardsList/NoBoardBoard.tsx | 9 +- .../Boards/GalleryBoardContextMenuItems.tsx | 39 +---- .../Boards/NoBoardContextMenuItems.tsx | 15 +- .../CurrentImage/CurrentImageButtons.tsx | 2 +- .../CurrentImage/CurrentImagePreview.tsx | 11 +- .../components/ImageGalleryContent.tsx | 8 +- .../components/ImageGrid/BatchImage.tsx | 36 ++--- .../components/ImageGrid/GalleryImage.tsx | 26 ++- .../features/gallery/store/gallerySlice.ts | 68 ++++---- .../fields/ArrayInputFieldComponent.tsx | 4 +- .../fields/ClipInputFieldComponent.tsx | 4 +- .../ConditioningInputFieldComponent.tsx | 4 +- .../fields/ControlInputFieldComponent.tsx | 4 +- .../ControlNetModelInputFieldComponent.tsx | 2 - .../ImageCollectionInputFieldComponent.tsx | 59 +++---- .../fields/ImageInputFieldComponent.tsx | 27 ++-- .../fields/ItemInputFieldComponent.tsx | 4 +- .../fields/LatentsInputFieldComponent.tsx | 4 +- .../fields/UnetInputFieldComponent.tsx | 3 +- .../fields/VaeInputFieldComponent.tsx | 3 +- .../fields/VaeModelInputFieldComponent.tsx | 2 - .../nodes/components/search/NodeSearch.tsx | 13 +- .../nodes/hooks/useIsValidConnection.ts | 153 +++++++++--------- .../nodes/util/fieldTemplateBuilders.ts | 4 + .../util/graphBuilders/buildNodesGraph.ts | 6 +- .../src/features/nodes/util/parseSchema.ts | 2 + .../ControlNet/ParamControlNetCollapse.tsx | 2 - .../components/Parameters/Core/ParamWidth.tsx | 2 +- .../Parameters/ImageToImage/InitialImage.tsx | 9 +- .../Parameters/Noise/ParamCpuNoise.tsx | 3 - .../Parameters/Noise/ParamNoiseToggle.tsx | 3 - .../Upscale/ParamRealESRGANModel.tsx | 1 - .../Variations/ParamVariationToggle.tsx | 3 - .../_ImageDimensions/AspectRatioPreview.tsx | 75 --------- .../_ImageDimensions/DimensionsSettings.tsx | 76 --------- .../parameters/hooks/useRecallParameters.ts | 1 - .../parameters/store/generationSlice.ts | 2 +- .../util/modelIdToControlNetModelParam.ts | 2 +- .../util/modelIdToLoRAModelParam.ts | 2 +- .../util/modelIdToMainModelParam.ts | 2 +- .../parameters/util/modelIdToVAEModelParam.ts | 2 +- .../system/components/StatusIndicator.tsx | 9 +- .../ui/components/ParametersPinnedWrapper.tsx | 1 - .../ImageToImageTabCoreParameters.tsx | 7 +- invokeai/frontend/web/src/i18n.ts | 3 +- .../services/events/util/setEventListeners.ts | 4 +- .../web/src/theme/components/button.ts | 8 +- .../web/src/theme/components/modal.ts | 8 +- 95 files changed, 333 insertions(+), 670 deletions(-) delete mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/AspectRatioPreview.tsx delete mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/DimensionsSettings.tsx diff --git a/invokeai/frontend/web/.prettierignore b/invokeai/frontend/web/.prettierignore index b351fc6a96..b23772e167 100644 --- a/invokeai/frontend/web/.prettierignore +++ b/invokeai/frontend/web/.prettierignore @@ -5,6 +5,10 @@ patches/ stats.html index.html .yarn/ +.yalc/ *.scss src/services/api/ src/services/fixtures/* +docs/ +static/ +src/theme/css/overlayscrollbars.css diff --git a/invokeai/frontend/web/src/app/logging/useLogger.ts b/invokeai/frontend/web/src/app/logging/useLogger.ts index 13c62edcd3..6c60bd4fd0 100644 --- a/invokeai/frontend/web/src/app/logging/useLogger.ts +++ b/invokeai/frontend/web/src/app/logging/useLogger.ts @@ -48,6 +48,8 @@ export const useLogger = () => { // Update the module-scoped logger context as needed useEffect(() => { + // TODO: type this properly + //eslint-disable-next-line @typescript-eslint/no-explicit-any const newContext: Record = { ...BASE_CONTEXT, }; diff --git a/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts b/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts index 5d94abd738..159952d654 100644 --- a/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts +++ b/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts @@ -12,7 +12,7 @@ import { defaultsDeep } from 'lodash-es'; import { UnserializeFunction } from 'redux-remember'; const initialStates: { - [key: string]: any; + [key: string]: object; // TODO: type this properly } = { canvas: initialCanvasState, gallery: initialGalleryState, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts index 315dd2f5f9..ee12f39a12 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/addFirstListImagesListener.ts.ts @@ -15,7 +15,7 @@ export const addFirstListImagesListener = () => { matcher: imagesApi.endpoints.listImages.matchFulfilled, effect: async ( action, - { getState, dispatch, unsubscribe, cancelActiveListeners } + { dispatch, unsubscribe, cancelActiveListeners } ) => { // Only run this listener on the first listImages request for no-board images if ( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/appStarted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/appStarted.ts index cfe9fd4a1c..189a5a3530 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/appStarted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/appStarted.ts @@ -6,10 +6,7 @@ export const appStarted = createAction('app/appStarted'); export const addAppStartedListener = () => { startAppListening({ actionCreator: appStarted, - effect: async ( - action, - { getState, dispatch, unsubscribe, cancelActiveListeners } - ) => { + effect: async (action, { unsubscribe, cancelActiveListeners }) => { // this should only run once cancelActiveListeners(); unsubscribe(); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts index 5320846e15..f0af52ced6 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardAndImagesDeleted.ts @@ -9,8 +9,8 @@ import { boardsApi } from '../../../../../services/api/endpoints/boards'; export const addDeleteBoardAndImagesFulfilledListener = () => { startAppListening({ matcher: boardsApi.endpoints.deleteBoardAndImages.matchFulfilled, - effect: async (action, { dispatch, getState, condition }) => { - const { board_id, deleted_board_images, deleted_images } = action.payload; + effect: async (action, { dispatch, getState }) => { + const { deleted_images } = action.payload; // Remove all deleted images from the UI diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts index c55eb7bc2b..21c506242d 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMerged.ts @@ -10,7 +10,7 @@ import { startAppListening } from '..'; export const addCanvasMergedListener = () => { startAppListening({ actionCreator: canvasMerged, - effect: async (action, { dispatch, getState, take }) => { + effect: async (action, { dispatch }) => { const moduleLog = $logger .get() .child({ namespace: 'canvasCopiedToClipboardListener' }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts index 8e7dc0c8ea..47f7aded27 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts @@ -8,7 +8,7 @@ import { startAppListening } from '..'; export const addCanvasSavedToGalleryListener = () => { startAppListening({ actionCreator: canvasSavedToGallery, - effect: async (action, { dispatch, getState, take }) => { + effect: async (action, { dispatch, getState }) => { const log = logger('canvas'); const state = getState(); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts index 3aa01d54cb..4a47e8d64e 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts @@ -62,10 +62,7 @@ const predicate: AnyListenerPredicate = ( export const addControlNetAutoProcessListener = () => { startAppListening({ predicate, - effect: async ( - action, - { dispatch, getState, cancelActiveListeners, delay } - ) => { + effect: async (action, { dispatch, cancelActiveListeners, delay }) => { const log = logger('session'); const { controlNetId } = action.payload; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts index 830585154c..313b2a02d8 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts @@ -1,4 +1,4 @@ -import { $logger, logger } from 'app/logging/logger'; +import { logger } from 'app/logging/logger'; import { controlNetImageProcessed } from 'features/controlNet/store/actions'; import { controlNetProcessedImageChanged } from 'features/controlNet/store/controlNetSlice'; import { sessionReadyToInvoke } from 'features/system/store/actions'; @@ -12,10 +12,7 @@ import { startAppListening } from '..'; export const addControlNetImageProcessedListener = () => { startAppListening({ actionCreator: controlNetImageProcessed, - effect: async ( - action, - { dispatch, getState, take, unsubscribe, subscribe } - ) => { + effect: async (action, { dispatch, getState, take }) => { const log = logger('session'); const { controlNetId } = action.payload; const controlNet = getState().controlNet.controlNets[controlNetId]; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts index eab627b3f4..039cbb657a 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageAddedToBoard.ts @@ -5,7 +5,7 @@ import { startAppListening } from '..'; export const addImageAddedToBoardFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.addImageToBoard.matchFulfilled, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('images'); const { board_id, imageDTO } = action.meta.arg.originalArgs; @@ -19,7 +19,7 @@ export const addImageAddedToBoardFulfilledListener = () => { export const addImageAddedToBoardRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.addImageToBoard.matchRejected, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('images'); const { board_id, imageDTO } = action.meta.arg.originalArgs; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts index 2643a461d7..428ce53219 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts @@ -19,7 +19,6 @@ export const addRequestedImageDeletionListener = () => { startAppListening({ actionCreator: imageDeletionConfirmed, effect: async (action, { dispatch, getState, condition }) => { - const log = logger('images'); const { imageDTO, imageUsage } = action.payload; dispatch(isModalOpenChanged(false)); @@ -104,8 +103,7 @@ export const addRequestedImageDeletionListener = () => { export const addImageDeletedPendingListener = () => { startAppListening({ matcher: imagesApi.endpoints.deleteImage.matchPending, - effect: (action, { dispatch, getState }) => { - const log = logger('images'); + effect: () => { // }, }); @@ -117,7 +115,7 @@ export const addImageDeletedPendingListener = () => { export const addImageDeletedFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.deleteImage.matchFulfilled, - effect: (action, { dispatch, getState }) => { + effect: (action) => { const log = logger('images'); log.debug({ imageDTO: action.meta.arg.originalArgs }, 'Image deleted'); }, @@ -130,7 +128,7 @@ export const addImageDeletedFulfilledListener = () => { export const addImageDeletedRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.deleteImage.matchRejected, - effect: (action, { dispatch, getState }) => { + effect: (action) => { const log = logger('images'); log.debug( { imageDTO: action.meta.arg.originalArgs }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts index 296bd0b953..fdf0849a12 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts @@ -23,7 +23,7 @@ export const dndDropped = createAction<{ export const addImageDroppedListener = () => { startAppListening({ actionCreator: dndDropped, - effect: async (action, { dispatch, getState, take }) => { + effect: async (action, { dispatch }) => { const log = logger('images'); const { activeData, overData } = action.payload; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts index 33c8dd5372..a8bf0e6791 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageRemovedFromBoard.ts @@ -5,7 +5,7 @@ import { startAppListening } from '..'; export const addImageRemovedFromBoardFulfilledListener = () => { startAppListening({ matcher: imagesApi.endpoints.removeImageFromBoard.matchFulfilled, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('images'); const imageDTO = action.meta.arg.originalArgs; @@ -17,7 +17,7 @@ export const addImageRemovedFromBoardFulfilledListener = () => { export const addImageRemovedFromBoardRejectedListener = () => { startAppListening({ matcher: imagesApi.endpoints.removeImageFromBoard.matchRejected, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('images'); const imageDTO = action.meta.arg.originalArgs; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts index 646cd259ad..3a5eed95db 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts @@ -9,7 +9,7 @@ import { startAppListening } from '..'; export const addImageToDeleteSelectedListener = () => { startAppListening({ actionCreator: imageToDeleteSelected, - effect: async (action, { dispatch, getState, condition }) => { + effect: async (action, { dispatch, getState }) => { const imageDTO = action.payload; const state = getState(); const { shouldConfirmOnDelete } = state.system; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts index 40c2209077..dd581d893c 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts @@ -9,6 +9,7 @@ import { addToast } from 'features/system/store/systemSlice'; import { boardsApi } from 'services/api/endpoints/boards'; import { startAppListening } from '..'; import { imagesApi } from '../../../../../services/api/endpoints/images'; +import { omit } from 'lodash-es'; const DEFAULT_UPLOADED_TOAST: UseToastOptions = { title: 'Image Uploaded', @@ -22,7 +23,7 @@ export const addImageUploadedFulfilledListener = () => { const log = logger('images'); const imageDTO = action.payload; const state = getState(); - const { selectedBoardId, autoAddBoardId } = state.gallery; + const { autoAddBoardId } = state.gallery; log.debug({ imageDTO }, 'Image uploaded'); @@ -140,8 +141,12 @@ export const addImageUploadedRejectedListener = () => { matcher: imagesApi.endpoints.uploadImage.matchRejected, effect: (action, { dispatch }) => { const log = logger('images'); - const { file, postUploadAction, ...rest } = action.meta.arg.originalArgs; - const sanitizedData = { arg: { ...rest, file: '' } }; + const sanitizedData = { + arg: { + ...omit(action.meta.arg.originalArgs, ['file', 'postUploadAction']), + file: '', + }, + }; log.error({ ...sanitizedData }, 'Image upload failed'); dispatch( addToast({ diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts index 17a52f2bfc..7748ca6fe5 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts @@ -8,7 +8,7 @@ import { startAppListening } from '..'; export const addInitialImageSelectedListener = () => { startAppListening({ actionCreator: initialImageSelected, - effect: (action, { getState, dispatch }) => { + effect: (action, { dispatch }) => { if (!action.payload) { dispatch( addToast( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts index 131898695a..57981918d8 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts @@ -1,4 +1,5 @@ -import { $logger, logger } from 'app/logging/logger'; +import { logger } from 'app/logging/logger'; +import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice'; import { loraRemoved } from 'features/lora/store/loraSlice'; import { modelChanged, @@ -11,7 +12,6 @@ import { import { forEach, some } from 'lodash-es'; import { modelsApi } from 'services/api/endpoints/models'; import { startAppListening } from '..'; -import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice'; export const addModelsLoadedListener = () => { startAppListening({ @@ -167,7 +167,7 @@ export const addModelsLoadedListener = () => { }); startAppListening({ matcher: modelsApi.endpoints.getTextualInversionModels.matchFulfilled, - effect: async (action, { getState, dispatch }) => { + effect: async (action) => { const log = logger('models'); log.info( { models: action.payload.entities }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts index e9bf690a27..44729f215a 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedOpenAPISchema.ts @@ -1,15 +1,15 @@ import { logger } from 'app/logging/logger'; +import { parseify } from 'common/util/serialize'; import { nodeTemplatesBuilt } from 'features/nodes/store/nodesSlice'; import { parseSchema } from 'features/nodes/util/parseSchema'; import { size } from 'lodash-es'; import { receivedOpenAPISchema } from 'services/api/thunks/schema'; import { startAppListening } from '..'; -import { parseify } from 'common/util/serialize'; export const addReceivedOpenAPISchemaListener = () => { startAppListening({ actionCreator: receivedOpenAPISchema.fulfilled, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('system'); const schemaJSON = action.payload; @@ -28,7 +28,7 @@ export const addReceivedOpenAPISchemaListener = () => { startAppListening({ actionCreator: receivedOpenAPISchema.rejected, - effect: (action, { dispatch, getState }) => { + effect: () => { const log = logger('system'); log.error('Problem dereferencing OpenAPI Schema'); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts index 2bc4ecad39..2592437348 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCanceled.ts @@ -6,8 +6,7 @@ import { startAppListening } from '..'; export const addSessionCanceledPendingListener = () => { startAppListening({ actionCreator: sessionCanceled.pending, - effect: (action, { getState, dispatch }) => { - const log = logger('session'); + effect: () => { // }, }); @@ -16,7 +15,7 @@ export const addSessionCanceledPendingListener = () => { export const addSessionCanceledFulfilledListener = () => { startAppListening({ actionCreator: sessionCanceled.fulfilled, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('session'); const { session_id } = action.meta.arg; log.debug({ session_id }, `Session canceled (${session_id})`); @@ -27,7 +26,7 @@ export const addSessionCanceledFulfilledListener = () => { export const addSessionCanceledRejectedListener = () => { startAppListening({ actionCreator: sessionCanceled.rejected, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('session'); const { session_id } = action.meta.arg; if (action.payload) { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts index eeaf725818..5709d87d22 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionCreated.ts @@ -7,8 +7,7 @@ import { startAppListening } from '..'; export const addSessionCreatedPendingListener = () => { startAppListening({ actionCreator: sessionCreated.pending, - effect: (action, { getState, dispatch }) => { - const log = logger('session'); + effect: () => { // }, }); @@ -17,7 +16,7 @@ export const addSessionCreatedPendingListener = () => { export const addSessionCreatedFulfilledListener = () => { startAppListening({ actionCreator: sessionCreated.fulfilled, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('session'); const session = action.payload; log.debug( @@ -31,10 +30,10 @@ export const addSessionCreatedFulfilledListener = () => { export const addSessionCreatedRejectedListener = () => { startAppListening({ actionCreator: sessionCreated.rejected, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('session'); if (action.payload) { - const { arg, error } = action.payload; + const { error } = action.payload; const graph = parseify(action.meta.arg); const stringifiedError = JSON.stringify(error); log.error( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts index 1c73f17444..60009ed194 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/sessionInvoked.ts @@ -6,8 +6,7 @@ import { startAppListening } from '..'; export const addSessionInvokedPendingListener = () => { startAppListening({ actionCreator: sessionInvoked.pending, - effect: (action, { getState, dispatch }) => { - const log = logger('session'); + effect: () => { // }, }); @@ -16,7 +15,7 @@ export const addSessionInvokedPendingListener = () => { export const addSessionInvokedFulfilledListener = () => { startAppListening({ actionCreator: sessionInvoked.fulfilled, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('session'); const { session_id } = action.meta.arg; log.debug({ session_id }, `Session invoked (${session_id})`); @@ -27,11 +26,11 @@ export const addSessionInvokedFulfilledListener = () => { export const addSessionInvokedRejectedListener = () => { startAppListening({ actionCreator: sessionInvoked.rejected, - effect: (action, { getState, dispatch }) => { + effect: (action) => { const log = logger('session'); const { session_id } = action.meta.arg; if (action.payload) { - const { arg, error } = action.payload; + const { error } = action.payload; const stringifiedError = JSON.stringify(error); log.error( { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts index cce2bbf52a..dfbdd25595 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketDisconnected.ts @@ -8,7 +8,7 @@ import { startAppListening } from '../..'; export const addSocketDisconnectedEventListener = () => { startAppListening({ actionCreator: socketDisconnected, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); log.debug('Disconnected'); // pass along the socket event as an application action diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts index 98a581ea1f..23ab9a8cb3 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketGraphExecutionStateComplete.ts @@ -8,7 +8,7 @@ import { startAppListening } from '../..'; export const addGraphExecutionStateCompleteEventListener = () => { startAppListening({ actionCreator: socketGraphExecutionStateComplete, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); log.debug(action.payload, 'Session complete'); // pass along the socket event as an application action diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts index 174a7de075..e36c49be63 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts @@ -22,7 +22,7 @@ const nodeDenylist = ['dataURL_image']; export const addInvocationCompleteEventListener = () => { startAppListening({ actionCreator: socketInvocationComplete, - effect: async (action, { dispatch, getState, take }) => { + effect: async (action, { dispatch, getState }) => { const log = logger('socketio'); const { data } = action.payload; log.debug( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts index d40ff1e944..ce15b8398c 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationError.ts @@ -8,7 +8,7 @@ import { startAppListening } from '../..'; export const addInvocationErrorEventListener = () => { startAppListening({ actionCreator: socketInvocationError, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); log.error( action.payload, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts index f221485c1f..0f3fabbc1e 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketModelLoad.ts @@ -1,5 +1,4 @@ import { logger } from 'app/logging/logger'; -import { ModelType } from 'services/api/types'; import { appSocketModelLoadCompleted, appSocketModelLoadStarted, @@ -8,18 +7,10 @@ import { } from 'services/events/actions'; import { startAppListening } from '../..'; -const MODEL_TYPES: Record = { - main: 'main', - vae: 'VAE', - lora: 'LoRA', - controlnet: 'ControlNet', - embedding: 'embedding', -}; - export const addModelLoadEventListener = () => { startAppListening({ actionCreator: socketModelLoadStarted, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); const { base_model, model_name, model_type, submodel } = action.payload.data; @@ -39,7 +30,7 @@ export const addModelLoadEventListener = () => { startAppListening({ actionCreator: socketModelLoadCompleted, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); const { base_model, model_name, model_type, submodel } = action.payload.data; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts index c01d6e915f..a05527790e 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketSubscribed.ts @@ -5,7 +5,7 @@ import { startAppListening } from '../..'; export const addSocketSubscribedEventListener = () => { startAppListening({ actionCreator: socketSubscribed, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); log.debug(action.payload, 'Subscribed'); dispatch(appSocketSubscribed(action.payload)); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts index d8baa2cf27..a8076ee1b7 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketUnsubscribed.ts @@ -8,7 +8,7 @@ import { startAppListening } from '../..'; export const addSocketUnsubscribedEventListener = () => { startAppListening({ actionCreator: socketUnsubscribed, - effect: (action, { dispatch, getState }) => { + effect: (action, { dispatch }) => { const log = logger('socketio'); log.debug(action.payload, 'Unsubscribed'); dispatch(appSocketUnsubscribed(action.payload)); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts index 5aea377624..a6818acbe0 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts @@ -1,4 +1,3 @@ -import { logger } from 'app/logging/logger'; import { stagingAreaImageSaved } from 'features/canvas/store/actions'; import { addToast } from 'features/system/store/systemSlice'; import { imagesApi } from 'services/api/endpoints/images'; @@ -7,8 +6,7 @@ import { startAppListening } from '..'; export const addStagingAreaImageSavedListener = () => { startAppListening({ actionCreator: stagingAreaImageSaved, - effect: async (action, { dispatch, getState, take }) => { - const log = logger('canvas'); + effect: async (action, { dispatch, getState }) => { const { imageDTO } = action.payload; try { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts index df597a3b62..75980a65e4 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts @@ -11,10 +11,7 @@ export const upscaleRequested = createAction<{ image_name: string }>( export const addUpscaleRequestedListener = () => { startAppListening({ actionCreator: upscaleRequested, - effect: async ( - action, - { dispatch, getState, take, unsubscribe, subscribe } - ) => { + effect: async (action, { dispatch, getState, take }) => { const { image_name } = action.payload; const { esrganModelName } = getState().postprocessing; diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index ad128a0fec..dd80e1e378 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -4,7 +4,6 @@ import { autoBatchEnhancer, combineReducers, configureStore, - createAsyncThunk, } from '@reduxjs/toolkit'; import canvasReducer from 'features/canvas/store/canvasSlice'; import controlNetReducer from 'features/controlNet/store/controlNetSlice'; @@ -118,6 +117,7 @@ export const store = configureStore({ export type AppGetState = typeof store.getState; export type RootState = ReturnType; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type AppThunkDispatch = ThunkDispatch; export type AppDispatch = typeof store.dispatch; export const stateSelector = (state: RootState) => state; diff --git a/invokeai/frontend/web/src/common/components/IAIDroppable.tsx b/invokeai/frontend/web/src/common/components/IAIDroppable.tsx index 2e41e3d870..1038f36840 100644 --- a/invokeai/frontend/web/src/common/components/IAIDroppable.tsx +++ b/invokeai/frontend/web/src/common/components/IAIDroppable.tsx @@ -13,11 +13,10 @@ type IAIDroppableProps = { dropLabel?: ReactNode; disabled?: boolean; data?: TypesafeDroppableData; - hoverRef?: React.Ref; }; const IAIDroppable = (props: IAIDroppableProps) => { - const { dropLabel, data, disabled, hoverRef } = props; + const { dropLabel, data, disabled } = props; const dndId = useRef(uuidv4()); const { isOver, setNodeRef, active } = useDroppable({ diff --git a/invokeai/frontend/web/src/common/components/IAIMantineSelectItemWithTooltip.tsx b/invokeai/frontend/web/src/common/components/IAIMantineSelectItemWithTooltip.tsx index 6b56bdf9e9..056bd4a8fa 100644 --- a/invokeai/frontend/web/src/common/components/IAIMantineSelectItemWithTooltip.tsx +++ b/invokeai/frontend/web/src/common/components/IAIMantineSelectItemWithTooltip.tsx @@ -10,7 +10,10 @@ interface ItemProps extends React.ComponentPropsWithoutRef<'div'> { } const IAIMantineSelectItemWithTooltip = forwardRef( - ({ label, tooltip, description, disabled, ...others }: ItemProps, ref) => ( + ( + { label, tooltip, description, disabled: _disabled, ...others }: ItemProps, + ref + ) => ( diff --git a/invokeai/frontend/web/src/common/components/IAISlider.tsx b/invokeai/frontend/web/src/common/components/IAISlider.tsx index 3e7f38cf91..53a195c7b7 100644 --- a/invokeai/frontend/web/src/common/components/IAISlider.tsx +++ b/invokeai/frontend/web/src/common/components/IAISlider.tsx @@ -1,5 +1,4 @@ import { - ChakraProps, FormControl, FormControlProps, FormLabel, @@ -24,16 +23,15 @@ import { Tooltip, TooltipProps, } from '@chakra-ui/react'; -import { clamp } from 'lodash-es'; - import { useAppDispatch } from 'app/store/storeHooks'; import { roundDownToMultiple } from 'common/util/roundDownToMultiple'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice'; +import { clamp } from 'lodash-es'; import { FocusEvent, KeyboardEvent, - memo, MouseEvent, + memo, useCallback, useEffect, useMemo, diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx index aa785c379d..7a82e64270 100644 --- a/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx +++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvas.tsx @@ -1,6 +1,7 @@ import { Box, chakra, Flex } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; +import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { canvasSelector, isStagingSelector, @@ -8,8 +9,6 @@ import { import Konva from 'konva'; import { KonvaEventObject } from 'konva/lib/Node'; import { Vector2d } from 'konva/lib/types'; -import { isEqual } from 'lodash-es'; - import { useCallback, useRef } from 'react'; import { Layer, Stage } from 'react-konva'; import useCanvasDragMove from '../hooks/useCanvasDragMove'; @@ -34,7 +33,6 @@ import IAICanvasStagingAreaToolbar from './IAICanvasStagingAreaToolbar'; import IAICanvasStatusText from './IAICanvasStatusText'; import IAICanvasBoundingBox from './IAICanvasToolbar/IAICanvasBoundingBox'; import IAICanvasToolPreview from './IAICanvasToolPreview'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; const selector = createSelector( [canvasSelector, isStagingSelector], diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts index 54ebfa2934..3163e513e9 100644 --- a/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts +++ b/invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts @@ -713,7 +713,7 @@ export const canvasSlice = createSlice({ }, commitStagingAreaImage: ( state, - action: PayloadAction + _action: PayloadAction ) => { if (!state.layerState.stagingArea.images.length) { return; @@ -866,11 +866,11 @@ export const canvasSlice = createSlice({ } }); - builder.addCase(setShouldUseCanvasBetaLayout, (state, action) => { + builder.addCase(setShouldUseCanvasBetaLayout, (state) => { state.doesCanvasNeedScaling = true; }); - builder.addCase(setActiveTab, (state, action) => { + builder.addCase(setActiveTab, (state) => { state.doesCanvasNeedScaling = true; }); builder.addCase(setAspectRatio, (state, action) => { @@ -882,26 +882,6 @@ export const canvasSlice = createSlice({ ); } }); - - // builder.addCase(imageUrlsReceived.fulfilled, (state, action) => { - // const { image_name, image_url, thumbnail_url } = action.payload; - - // state.layerState.objects.forEach((object) => { - // if (object.kind === 'image') { - // if (object.image.image_name === image_name) { - // object.image.image_url = image_url; - // object.image.thumbnail_url = thumbnail_url; - // } - // } - // }); - - // state.layerState.stagingArea.images.forEach((stagedImage) => { - // if (stagedImage.image.image_name === image_name) { - // stagedImage.image.image_url = image_url; - // stagedImage.image.thumbnail_url = thumbnail_url; - // } - // }); - // }); }, }); diff --git a/invokeai/frontend/web/src/features/controlNet/components/ControlNetImagePreview.tsx b/invokeai/frontend/web/src/features/controlNet/components/ControlNetImagePreview.tsx index 1bdb2fd034..859495a941 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/ControlNetImagePreview.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/ControlNetImagePreview.tsx @@ -11,8 +11,8 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAIDndImage from 'common/components/IAIDndImage'; import { memo, useCallback, useMemo, useState } from 'react'; import { useGetImageDTOQuery } from 'services/api/endpoints/images'; -import { controlNetImageChanged } from '../store/controlNetSlice'; import { PostUploadAction } from 'services/api/types'; +import { controlNetImageChanged } from '../store/controlNetSlice'; type Props = { controlNetId: string; @@ -59,19 +59,13 @@ const ControlNetImagePreview = (props: Props) => { const [isMouseOverImage, setIsMouseOverImage] = useState(false); - const { - currentData: controlImage, - isLoading: isLoadingControlImage, - isError: isErrorControlImage, - isSuccess: isSuccessControlImage, - } = useGetImageDTOQuery(controlImageName ?? skipToken); + const { currentData: controlImage } = useGetImageDTOQuery( + controlImageName ?? skipToken + ); - const { - currentData: processedControlImage, - isLoading: isLoadingProcessedControlImage, - isError: isErrorProcessedControlImage, - isSuccess: isSuccessProcessedControlImage, - } = useGetImageDTOQuery(processedControlImageName ?? skipToken); + const { currentData: processedControlImage } = useGetImageDTOQuery( + processedControlImageName ?? skipToken + ); const handleResetControlImage = useCallback(() => { dispatch(controlNetImageChanged({ controlNetId, controlImage: null })); diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx index f2f8a8bef2..3dd420e7c9 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetBeginEnd.tsx @@ -55,11 +55,6 @@ const ParamControlNetBeginEnd = (props: Props) => { [controlNetId, dispatch] ); - const handleStepPctReset = useCallback(() => { - dispatch(controlNetBeginStepPctChanged({ controlNetId, beginStepPct: 0 })); - dispatch(controlNetEndStepPctChanged({ controlNetId, endStepPct: 1 })); - }, [controlNetId, dispatch]); - return ( Begin / End Step Percentage diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx index e2995cf993..e644e24a02 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetControlMode.tsx @@ -8,7 +8,6 @@ import { controlNetControlModeChanged, } from 'features/controlNet/store/controlNetSlice'; import { useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; type ParamControlNetControlModeProps = { controlNetId: string; @@ -42,8 +41,6 @@ export default function ParamControlNetControlMode( const { controlMode, isEnabled } = useAppSelector(selector); - const { t } = useTranslation(); - const handleControlModeChange = useCallback( (controlMode: ControlModes) => { dispatch(controlNetControlModeChanged({ controlNetId, controlMode })); diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetProcessorSelect.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetProcessorSelect.tsx index 8bd28f813c..83c66363ac 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetProcessorSelect.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetProcessorSelect.tsx @@ -13,7 +13,6 @@ import { memo, useCallback, useMemo } from 'react'; import { CONTROLNET_PROCESSORS } from '../../store/constants'; import { controlNetProcessorTypeChanged } from '../../store/controlNetSlice'; import { ControlNetProcessorType } from '../../store/types'; -import { FormControl, FormLabel } from '@chakra-ui/react'; type ParamControlNetProcessorSelectProps = { controlNetId: string; diff --git a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx index 4b31ebfc64..ee04b8077f 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/parameters/ParamControlNetResizeMode.tsx @@ -8,7 +8,6 @@ import { controlNetResizeModeChanged, } from 'features/controlNet/store/controlNetSlice'; import { useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; type ParamControlNetResizeModeProps = { controlNetId: string; @@ -41,8 +40,6 @@ export default function ParamControlNetResizeMode( const { resizeMode, isEnabled } = useAppSelector(selector); - const { t } = useTranslation(); - const handleResizeModeChange = useCallback( (resizeMode: ResizeModes) => { dispatch(controlNetResizeModeChanged({ controlNetId, resizeMode })); diff --git a/invokeai/frontend/web/src/features/controlNet/components/processors/ZoeDepthProcessor.tsx b/invokeai/frontend/web/src/features/controlNet/components/processors/ZoeDepthProcessor.tsx index b4b45025eb..1842f39e45 100644 --- a/invokeai/frontend/web/src/features/controlNet/components/processors/ZoeDepthProcessor.tsx +++ b/invokeai/frontend/web/src/features/controlNet/components/processors/ZoeDepthProcessor.tsx @@ -7,7 +7,7 @@ type Props = { isEnabled: boolean; }; -const ZoeDepthProcessor = (props: Props) => { +const ZoeDepthProcessor = (_props: Props) => { // Has no parameters? return null; }; diff --git a/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts b/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts index 196023491c..0df907d463 100644 --- a/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts +++ b/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts @@ -314,11 +314,11 @@ export const controlNetSlice = createSlice({ } }); - builder.addCase(appSocketInvocationError, (state, action) => { + builder.addCase(appSocketInvocationError, (state) => { state.pendingControlImages = []; }); - builder.addMatcher(isAnySessionRejected, (state, action) => { + builder.addMatcher(isAnySessionRejected, (state) => { state.pendingControlImages = []; }); diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardContextMenu.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardContextMenu.tsx index 4ce85afb1a..35fcbd87f7 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardContextMenu.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardContextMenu.tsx @@ -1,19 +1,16 @@ import { MenuGroup, MenuItem, MenuList } from '@chakra-ui/react'; +import { createSelector } from '@reduxjs/toolkit'; +import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { ContextMenu, ContextMenuProps } from 'chakra-ui-contextmenu'; -import { - autoAddBoardIdChanged, - boardIdSelected, -} from 'features/gallery/store/gallerySlice'; +import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice'; import { MouseEvent, memo, useCallback, useMemo } from 'react'; -import { FaFolder, FaPlus } from 'react-icons/fa'; +import { FaPlus } from 'react-icons/fa'; +import { useBoardName } from 'services/api/hooks/useBoardName'; import { BoardDTO } from 'services/api/types'; import { menuListMotionProps } from 'theme/components/menu'; import GalleryBoardContextMenuItems from './GalleryBoardContextMenuItems'; import NoBoardContextMenuItems from './NoBoardContextMenuItems'; -import { useBoardName } from 'services/api/hooks/useBoardName'; -import { createSelector } from '@reduxjs/toolkit'; -import { stateSelector } from 'app/store/store'; type Props = { board?: BoardDTO; @@ -29,20 +26,15 @@ const BoardContextMenu = memo( const selector = useMemo( () => createSelector(stateSelector, ({ gallery }) => { - const isSelected = gallery.selectedBoardId === board_id; const isAutoAdd = gallery.autoAddBoardId === board_id; - return { isSelected, isAutoAdd }; + return { isAutoAdd }; }), [board_id] ); - const { isSelected, isAutoAdd } = useAppSelector(selector); + const { isAutoAdd } = useAppSelector(selector); const boardName = useBoardName(board_id); - const handleSelectBoard = useCallback(() => { - dispatch(boardIdSelected(board_id)); - }, [board_id, dispatch]); - const handleSetAutoAdd = useCallback(() => { dispatch(autoAddBoardIdChanged(board_id)); }, [board_id, dispatch]); diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx index f20bb5a245..512fced67c 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/BoardsList.tsx @@ -1,21 +1,16 @@ -import { ButtonGroup, Collapse, Flex, Grid, GridItem } from '@chakra-ui/react'; +import { Collapse, Flex, Grid, GridItem } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { stateSelector } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import IAIIconButton from 'common/components/IAIIconButton'; -import { AnimatePresence, motion } from 'framer-motion'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; -import { memo, useCallback, useState } from 'react'; -import { FaSearch } from 'react-icons/fa'; +import { memo, useState } from 'react'; import { useListAllBoardsQuery } from 'services/api/endpoints/boards'; import { BoardDTO } from 'services/api/types'; -import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus'; import DeleteBoardModal from '../DeleteBoardModal'; import AddBoardButton from './AddBoardButton'; import BoardsSearch from './BoardsSearch'; import GalleryBoard from './GalleryBoard'; -import SystemBoardButton from './SystemBoardButton'; import NoBoardBoard from './NoBoardBoard'; const selector = createSelector( @@ -36,7 +31,6 @@ const BoardsList = (props: Props) => { const { isOpen } = props; const { selectedBoardId, searchText } = useAppSelector(selector); const { data: boards } = useListAllBoardsQuery(); - const isBatchEnabled = useFeatureStatus('batches').isFeatureEnabled; const filteredBoards = searchText ? boards?.filter((board) => board.board_name.toLowerCase().includes(searchText.toLowerCase()) diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx index dc484ec230..67c45c131b 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/GalleryBoard.tsx @@ -1,7 +1,5 @@ import { - Badge, Box, - ChakraProps, Editable, EditableInput, EditablePreview, @@ -17,21 +15,16 @@ import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAIDroppable from 'common/components/IAIDroppable'; +import SelectionOverlay from 'common/components/SelectionOverlay'; import { boardIdSelected } from 'features/gallery/store/gallerySlice'; import { memo, useCallback, useMemo, useState } from 'react'; import { FaUser } from 'react-icons/fa'; import { useUpdateBoardMutation } from 'services/api/endpoints/boards'; import { useGetImageDTOQuery } from 'services/api/endpoints/images'; -import { useBoardTotal } from 'services/api/hooks/useBoardTotal'; import { BoardDTO } from 'services/api/types'; import AutoAddIcon from '../AutoAddIcon'; import BoardContextMenu from '../BoardContextMenu'; -import SelectionOverlay from 'common/components/SelectionOverlay'; -const BASE_BADGE_STYLES: ChakraProps['sx'] = { - bg: 'base.500', - color: 'whiteAlpha.900', -}; interface GalleryBoardProps { board: BoardDTO; isSelected: boolean; @@ -68,8 +61,6 @@ const GalleryBoard = memo( board.cover_image_name ?? skipToken ); - const { totalImages, totalAssets } = useBoardTotal(board.board_id); - const { board_name, board_id } = board; const [localBoardName, setLocalBoardName] = useState(board_name); diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx index 2674eee6f3..ee1d8f6bea 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/NoBoardBoard.tsx @@ -1,4 +1,4 @@ -import { Box, ChakraProps, Flex, Image, Text } from '@chakra-ui/react'; +import { Box, Flex, Image, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { MoveBoardDropData } from 'app/components/ImageDnd/typesafeDnd'; import { stateSelector } from 'app/store/store'; @@ -10,14 +10,8 @@ import SelectionOverlay from 'common/components/SelectionOverlay'; import { boardIdSelected } from 'features/gallery/store/gallerySlice'; import { memo, useCallback, useMemo, useState } from 'react'; import { useBoardName } from 'services/api/hooks/useBoardName'; -import { useBoardTotal } from 'services/api/hooks/useBoardTotal'; import AutoAddIcon from '../AutoAddIcon'; import BoardContextMenu from '../BoardContextMenu'; - -const BASE_BADGE_STYLES: ChakraProps['sx'] = { - bg: 'base.500', - color: 'whiteAlpha.900', -}; interface Props { isSelected: boolean; } @@ -33,7 +27,6 @@ const selector = createSelector( const NoBoardBoard = memo(({ isSelected }: Props) => { const dispatch = useAppDispatch(); - const { totalImages, totalAssets } = useBoardTotal(undefined); const { autoAddBoardId } = useAppSelector(selector); const boardName = useBoardName(undefined); const handleSelectBoard = useCallback(() => { diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/GalleryBoardContextMenuItems.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/GalleryBoardContextMenuItems.tsx index 4b036bfe7c..9499e6be98 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/GalleryBoardContextMenuItems.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/GalleryBoardContextMenuItems.tsx @@ -1,11 +1,6 @@ import { MenuItem } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { stateSelector } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice'; -import { memo, useCallback, useMemo } from 'react'; -import { FaPlus, FaTrash } from 'react-icons/fa'; +import { memo, useCallback } from 'react'; +import { FaTrash } from 'react-icons/fa'; import { BoardDTO } from 'services/api/types'; type Props = { @@ -14,25 +9,6 @@ type Props = { }; const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => { - const dispatch = useAppDispatch(); - - const selector = useMemo( - () => - createSelector( - stateSelector, - ({ gallery }) => { - const isSelectedForAutoAdd = - board.board_id === gallery.autoAddBoardId; - - return { isSelectedForAutoAdd }; - }, - defaultSelectorOptions - ), - [board.board_id] - ); - - const { isSelectedForAutoAdd } = useAppSelector(selector); - const handleDelete = useCallback(() => { if (!setBoardToDelete) { return; @@ -40,12 +16,6 @@ const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => { setBoardToDelete(board); }, [board, setBoardToDelete]); - const handleToggleAutoAdd = useCallback(() => { - dispatch( - autoAddBoardIdChanged(isSelectedForAutoAdd ? undefined : board.board_id) - ); - }, [board.board_id, dispatch, isSelectedForAutoAdd]); - return ( <> {board.image_count > 0 && ( @@ -59,11 +29,6 @@ const GalleryBoardContextMenuItems = ({ board, setBoardToDelete }: Props) => { */} )} - {/* {!isSelectedForAutoAdd && ( - } onClick={handleToggleAutoAdd}> - Auto-add to this Board - - )} */} } diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/NoBoardContextMenuItems.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/NoBoardContextMenuItems.tsx index 31366f6e6a..dd7c7234ce 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/NoBoardContextMenuItems.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/NoBoardContextMenuItems.tsx @@ -1,19 +1,6 @@ -import { MenuItem } from '@chakra-ui/react'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { autoAddBoardIdChanged } from 'features/gallery/store/gallerySlice'; -import { memo, useCallback } from 'react'; -import { FaPlus } from 'react-icons/fa'; +import { memo } from 'react'; const NoBoardContextMenuItems = () => { - const dispatch = useAppDispatch(); - - const autoAddBoardId = useAppSelector( - (state) => state.gallery.autoAddBoardId - ); - const handleDisableAutoAdd = useCallback(() => { - dispatch(autoAddBoardIdChanged(undefined)); - }, [dispatch]); - return ( <> {/* {autoAddBoardId && ( diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImageButtons.tsx index 0cf3671db0..870c6d8461 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImageButtons.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImageButtons.tsx @@ -108,7 +108,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => { 500 ); - const { currentData: imageDTO, isFetching } = useGetImageDTOQuery( + const { currentData: imageDTO } = useGetImageDTOQuery( lastSelectedImage ?? skipToken ); diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImagePreview.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImagePreview.tsx index 52e26c55e7..fd7eaef46a 100644 --- a/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImagePreview.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImage/CurrentImagePreview.tsx @@ -8,17 +8,17 @@ import { import { stateSelector } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import IAIDndImage from 'common/components/IAIDndImage'; +import { IAINoContentFallback } from 'common/components/IAIImageFallback'; import { useNextPrevImage } from 'features/gallery/hooks/useNextPrevImage'; import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors'; import { AnimatePresence, motion } from 'framer-motion'; import { isEqual } from 'lodash-es'; import { memo, useCallback, useMemo, useRef, useState } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; +import { FaImage } from 'react-icons/fa'; import { useGetImageDTOQuery } from 'services/api/endpoints/images'; import ImageMetadataViewer from '../ImageMetadataViewer/ImageMetadataViewer'; import NextPrevImageButtons from '../NextPrevImageButtons'; -import { IAINoContentFallback } from 'common/components/IAIImageFallback'; -import { FaImage } from 'react-icons/fa'; export const imagesSelector = createSelector( [stateSelector, selectLastSelectedImage], @@ -93,12 +93,7 @@ const CurrentImagePreview = () => { ] ); - const { - currentData: imageDTO, - isLoading, - isError, - isSuccess, - } = useGetImageDTOQuery(imageName ?? skipToken); + const { currentData: imageDTO } = useGetImageDTOQuery(imageName ?? skipToken); const draggableData = useMemo(() => { if (imageDTO) { diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx index d384d66e58..5b2072bfc4 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx @@ -1,9 +1,7 @@ import { Box, - Button, ButtonGroup, Flex, - Spacer, Tab, TabList, Tabs, @@ -14,16 +12,16 @@ import { createSelector } from '@reduxjs/toolkit'; import { stateSelector } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; +import IAIButton from 'common/components/IAIButton'; import { memo, useCallback, useRef } from 'react'; +import { FaImages, FaServer } from 'react-icons/fa'; +import { galleryViewChanged } from '../store/gallerySlice'; import BoardsList from './Boards/BoardsList/BoardsList'; import GalleryBoardName from './GalleryBoardName'; import GalleryPinButton from './GalleryPinButton'; import GallerySettingsPopover from './GallerySettingsPopover'; import BatchImageGrid from './ImageGrid/BatchImageGrid'; import GalleryImageGrid from './ImageGrid/GalleryImageGrid'; -import IAIButton from 'common/components/IAIButton'; -import { FaImages, FaServer } from 'react-icons/fa'; -import { galleryViewChanged } from '../store/gallerySlice'; const selector = createSelector( [stateSelector], diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/BatchImage.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/BatchImage.tsx index a918682ccd..528e8cc06f 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageGrid/BatchImage.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageGrid/BatchImage.tsx @@ -8,13 +8,8 @@ import IAIDndImage from 'common/components/IAIDndImage'; import IAIErrorLoadingImageFallback from 'common/components/IAIErrorLoadingImageFallback'; import IAIFillSkeleton from 'common/components/IAIFillSkeleton'; import ImageContextMenu from 'features/gallery/components/ImageContextMenu/ImageContextMenu'; -import { - imageRangeEndSelected, - imageSelected, - imageSelectionToggled, - imagesRemovedFromBatch, -} from 'features/gallery/store/gallerySlice'; -import { MouseEvent, memo, useCallback, useMemo } from 'react'; +import { imagesRemovedFromBatch } from 'features/gallery/store/gallerySlice'; +import { memo, useCallback, useMemo } from 'react'; import { useGetImageDTOQuery } from 'services/api/endpoints/images'; const makeSelector = (image_name: string) => @@ -39,7 +34,6 @@ const BatchImage = (props: BatchImageProps) => { currentData: imageDTO, isLoading, isError, - isSuccess, } = useGetImageDTOQuery(imageName); const selector = useMemo(() => makeSelector(imageName), [imageName]); @@ -49,18 +43,18 @@ const BatchImage = (props: BatchImageProps) => { dispatch(imagesRemovedFromBatch([imageName])); }, [dispatch, imageName]); - const handleClick = useCallback( - (e: MouseEvent) => { - if (e.shiftKey) { - dispatch(imageRangeEndSelected(imageName)); - } else if (e.ctrlKey || e.metaKey) { - dispatch(imageSelectionToggled(imageName)); - } else { - dispatch(imageSelected(imageName)); - } - }, - [dispatch, imageName] - ); + // const handleClick = useCallback( + // (e: MouseEvent) => { + // if (e.shiftKey) { + // dispatch(imageRangeEndSelected(imageName)); + // } else if (e.ctrlKey || e.metaKey) { + // dispatch(imageSelectionToggled(imageName)); + // } else { + // dispatch(imageSelected(imageName)); + // } + // }, + // [dispatch, imageName] + // ); const draggableData = useMemo(() => { if (selectionCount > 1) { @@ -105,7 +99,7 @@ const BatchImage = (props: BatchImageProps) => { }} > { const { isSelected, selectionCount, selection } = useAppSelector(localSelector); - const handleClick = useCallback( - (e: MouseEvent) => { - // disable multiselect for now - // if (e.shiftKey) { - // dispatch(imageRangeEndSelected(imageName)); - // } else if (e.ctrlKey || e.metaKey) { - // dispatch(imageSelectionToggled(imageName)); - // } else { - // dispatch(imageSelected(imageName)); - // } - dispatch(imageSelected(imageName)); - }, - [dispatch, imageName] - ); + const handleClick = useCallback(() => { + // disable multiselect for now + // if (e.shiftKey) { + // dispatch(imageRangeEndSelected(imageName)); + // } else if (e.ctrlKey || e.metaKey) { + // dispatch(imageSelectionToggled(imageName)); + // } else { + // dispatch(imageSelected(imageName)); + // } + dispatch(imageSelected(imageName)); + }, [dispatch, imageName]); const handleDelete = useCallback( (e: MouseEvent) => { diff --git a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts index 125463ba94..5eabe5de26 100644 --- a/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts +++ b/invokeai/frontend/web/src/features/gallery/store/gallerySlice.ts @@ -19,40 +19,44 @@ export const gallerySlice = createSlice({ name: 'gallery', initialState: initialGalleryState, reducers: { - imageRangeEndSelected: (state, action: PayloadAction) => { - // TODO: multiselect - // const rangeEndImageName = action.payload; - // const lastSelectedImage = state.selection[state.selection.length - 1]; - // const filteredImages = selectFilteredImagesLocal(state); - // const lastClickedIndex = filteredImages.findIndex( - // (n) => n.image_name === lastSelectedImage - // ); - // const currentClickedIndex = filteredImages.findIndex( - // (n) => n.image_name === rangeEndImageName - // ); - // if (lastClickedIndex > -1 && currentClickedIndex > -1) { - // // We have a valid range! - // const start = Math.min(lastClickedIndex, currentClickedIndex); - // const end = Math.max(lastClickedIndex, currentClickedIndex); - // const imagesToSelect = filteredImages - // .slice(start, end + 1) - // .map((i) => i.image_name); - // state.selection = uniq(state.selection.concat(imagesToSelect)); - // } + imageRangeEndSelected: () => { + // TODO }, - imageSelectionToggled: (state, action: PayloadAction) => { - // TODO: multiselect - // if ( - // state.selection.includes(action.payload) && - // state.selection.length > 1 - // ) { - // state.selection = state.selection.filter( - // (imageName) => imageName !== action.payload - // ); - // } else { - // state.selection = uniq(state.selection.concat(action.payload)); - // } + // imageRangeEndSelected: (state, action: PayloadAction) => { + // const rangeEndImageName = action.payload; + // const lastSelectedImage = state.selection[state.selection.length - 1]; + // const filteredImages = selectFilteredImagesLocal(state); + // const lastClickedIndex = filteredImages.findIndex( + // (n) => n.image_name === lastSelectedImage + // ); + // const currentClickedIndex = filteredImages.findIndex( + // (n) => n.image_name === rangeEndImageName + // ); + // if (lastClickedIndex > -1 && currentClickedIndex > -1) { + // // We have a valid range! + // const start = Math.min(lastClickedIndex, currentClickedIndex); + // const end = Math.max(lastClickedIndex, currentClickedIndex); + // const imagesToSelect = filteredImages + // .slice(start, end + 1) + // .map((i) => i.image_name); + // state.selection = uniq(state.selection.concat(imagesToSelect)); + // } + // }, + imageSelectionToggled: () => { + // TODO }, + // imageSelectionToggled: (state, action: PayloadAction) => { + // TODO: multiselect + // if ( + // state.selection.includes(action.payload) && + // state.selection.length > 1 + // ) { + // state.selection = state.selection.filter( + // (imageName) => imageName !== action.payload + // ); + // } else { + // state.selection = uniq(state.selection.concat(action.payload)); + // } imageSelected: (state, action: PayloadAction) => { state.selection = action.payload ? [action.payload] : []; }, diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ArrayInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ArrayInputFieldComponent.tsx index 6f437dfcd8..8e478c907c 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ArrayInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ArrayInputFieldComponent.tsx @@ -7,10 +7,8 @@ import { FaList } from 'react-icons/fa'; import { FieldComponentProps } from './types'; const ArrayInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; - return ; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ClipInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ClipInputFieldComponent.tsx index 86359dc9b5..37c3db3d11 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ClipInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ClipInputFieldComponent.tsx @@ -6,10 +6,8 @@ import { memo } from 'react'; import { FieldComponentProps } from './types'; const ClipInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; - return null; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ConditioningInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ConditioningInputFieldComponent.tsx index 29ce1e8dae..e280251cd3 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ConditioningInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ConditioningInputFieldComponent.tsx @@ -6,13 +6,11 @@ import { memo } from 'react'; import { FieldComponentProps } from './types'; const ConditioningInputFieldComponent = ( - props: FieldComponentProps< + _props: FieldComponentProps< ConditioningInputFieldValue, ConditioningInputFieldTemplate > ) => { - const { nodeId, field } = props; - return null; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ControlInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ControlInputFieldComponent.tsx index dacfdf0703..6b2b3deafb 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ControlInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ControlInputFieldComponent.tsx @@ -6,10 +6,8 @@ import { memo } from 'react'; import { FieldComponentProps } from './types'; const ControlInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; - return null; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ControlNetModelInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ControlNetModelInputFieldComponent.tsx index b5d9fef312..7fe2373f66 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ControlNetModelInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ControlNetModelInputFieldComponent.tsx @@ -10,7 +10,6 @@ import { MODEL_TYPE_MAP } from 'features/parameters/types/constants'; import { modelIdToControlNetModelParam } from 'features/parameters/util/modelIdToControlNetModelParam'; import { forEach } from 'lodash-es'; import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { useGetControlNetModelsQuery } from 'services/api/endpoints/models'; import { FieldComponentProps } from './types'; @@ -23,7 +22,6 @@ const ControlNetModelInputFieldComponent = ( const { nodeId, field } = props; const controlNetModel = field.value; const dispatch = useAppDispatch(); - const { t } = useTranslation(); const { data: controlNetModels } = useGetControlNetModelsQuery(); diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ImageCollectionInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ImageCollectionInputFieldComponent.tsx index 0ac1f7aa1c..8ecd6c8cd9 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ImageCollectionInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ImageCollectionInputFieldComponent.tsx @@ -1,25 +1,19 @@ -import { useAppDispatch } from 'app/store/storeHooks'; - -import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; import { ImageCollectionInputFieldTemplate, ImageCollectionInputFieldValue, } from 'features/nodes/types/types'; -import { memo, useCallback } from 'react'; +import { memo } from 'react'; -import { FieldComponentProps } from './types'; -import IAIDndImage from 'common/components/IAIDndImage'; -import { ImageDTO } from 'services/api/types'; import { Flex } from '@chakra-ui/react'; -import { useGetImageDTOQuery } from 'services/api/endpoints/images'; -import { skipToken } from '@reduxjs/toolkit/dist/query'; -import { uniq, uniqBy } from 'lodash-es'; import { NodesMultiImageDropData, isValidDrop, useDroppable, } from 'app/components/ImageDnd/typesafeDnd'; +import IAIDndImage from 'common/components/IAIDndImage'; import IAIDropOverlay from 'common/components/IAIDropOverlay'; +import { useGetImageDTOQuery } from 'services/api/endpoints/images'; +import { FieldComponentProps } from './types'; const ImageCollectionInputFieldComponent = ( props: FieldComponentProps< @@ -29,20 +23,20 @@ const ImageCollectionInputFieldComponent = ( ) => { const { nodeId, field } = props; - const dispatch = useAppDispatch(); + // const dispatch = useAppDispatch(); - const handleDrop = useCallback( - ({ image_name }: ImageDTO) => { - dispatch( - fieldValueChanged({ - nodeId, - fieldName: field.name, - value: uniqBy([...(field.value ?? []), { image_name }], 'image_name'), - }) - ); - }, - [dispatch, field.name, field.value, nodeId] - ); + // const handleDrop = useCallback( + // ({ image_name }: ImageDTO) => { + // dispatch( + // fieldValueChanged({ + // nodeId, + // fieldName: field.name, + // value: uniqBy([...(field.value ?? []), { image_name }], 'image_name'), + // }) + // ); + // }, + // [dispatch, field.name, field.value, nodeId] + // ); const droppableData: NodesMultiImageDropData = { id: `node-${nodeId}-${field.name}`, @@ -54,21 +48,20 @@ const ImageCollectionInputFieldComponent = ( isOver, setNodeRef: setDroppableRef, active, - over, } = useDroppable({ id: `node_${nodeId}`, data: droppableData, }); - const handleReset = useCallback(() => { - dispatch( - fieldValueChanged({ - nodeId, - fieldName: field.name, - value: undefined, - }) - ); - }, [dispatch, field.name, nodeId]); + // const handleReset = useCallback(() => { + // dispatch( + // fieldValueChanged({ + // nodeId, + // fieldName: field.name, + // value: undefined, + // }) + // ); + // }, [dispatch, field.name, nodeId]); return ( @@ -25,12 +23,9 @@ const ImageInputFieldComponent = ( const dispatch = useAppDispatch(); - const { - currentData: imageDTO, - isLoading, - isError, - isSuccess, - } = useGetImageDTOQuery(field.value?.image_name ?? skipToken); + const { currentData: imageDTO } = useGetImageDTOQuery( + field.value?.image_name ?? skipToken + ); const handleReset = useCallback(() => { dispatch( diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/ItemInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/ItemInputFieldComponent.tsx index fa8eb5a26d..6fa89345bf 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/ItemInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/ItemInputFieldComponent.tsx @@ -7,10 +7,8 @@ import { FaAddressCard } from 'react-icons/fa'; import { FieldComponentProps } from './types'; const ItemInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; - return ; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/LatentsInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/LatentsInputFieldComponent.tsx index 2de0a07eb5..5d5225582c 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/LatentsInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/LatentsInputFieldComponent.tsx @@ -6,10 +6,8 @@ import { memo } from 'react'; import { FieldComponentProps } from './types'; const LatentsInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; - return null; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/UnetInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/UnetInputFieldComponent.tsx index 2b5438e802..eaf760d5d4 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/UnetInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/UnetInputFieldComponent.tsx @@ -6,9 +6,8 @@ import { memo } from 'react'; import { FieldComponentProps } from './types'; const UNetInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; return null; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/VaeInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/VaeInputFieldComponent.tsx index b76e43830e..16c59368f9 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/VaeInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/VaeInputFieldComponent.tsx @@ -6,9 +6,8 @@ import { memo } from 'react'; import { FieldComponentProps } from './types'; const VaeInputFieldComponent = ( - props: FieldComponentProps + _props: FieldComponentProps ) => { - const { nodeId, field } = props; return null; }; diff --git a/invokeai/frontend/web/src/features/nodes/components/fields/VaeModelInputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/fields/VaeModelInputFieldComponent.tsx index e30532a92f..3fe04b6e29 100644 --- a/invokeai/frontend/web/src/features/nodes/components/fields/VaeModelInputFieldComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/fields/VaeModelInputFieldComponent.tsx @@ -11,7 +11,6 @@ import { MODEL_TYPE_MAP } from 'features/parameters/types/constants'; import { modelIdToVAEModelParam } from 'features/parameters/util/modelIdToVAEModelParam'; import { forEach } from 'lodash-es'; import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { useGetVaeModelsQuery } from 'services/api/endpoints/models'; import { FieldComponentProps } from './types'; @@ -24,7 +23,6 @@ const VaeModelInputFieldComponent = ( const { nodeId, field } = props; const vae = field.value; const dispatch = useAppDispatch(); - const { t } = useTranslation(); const { data: vaeModels } = useGetVaeModelsQuery(); const data = useMemo(() => { diff --git a/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx b/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx index c441297fe8..669110fa54 100644 --- a/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/search/NodeSearch.tsx @@ -1,26 +1,25 @@ import { Box, Flex } from '@chakra-ui/layout'; +import { Tooltip } from '@chakra-ui/tooltip'; +import { useAppToaster } from 'app/components/Toaster'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIInput from 'common/components/IAIInput'; +import { useBuildInvocation } from 'features/nodes/hooks/useBuildInvocation'; +import { InvocationTemplate } from 'features/nodes/types/types'; +import Fuse from 'fuse.js'; import { map } from 'lodash-es'; import { ChangeEvent, FocusEvent, KeyboardEvent, - memo, ReactNode, + memo, useCallback, useRef, useState, } from 'react'; -import { Tooltip } from '@chakra-ui/tooltip'; import { AnyInvocationType } from 'services/events/types'; -import { useBuildInvocation } from 'features/nodes/hooks/useBuildInvocation'; -import { addToast } from 'features/system/store/systemSlice'; import { nodeAdded } from '../../store/nodesSlice'; -import Fuse from 'fuse.js'; -import { InvocationTemplate } from 'features/nodes/types/types'; -import { useAppToaster } from 'app/components/Toaster'; interface NodeListItemProps { title: string; diff --git a/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts b/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts index a24267d9d9..e5bfa0a627 100644 --- a/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts +++ b/invokeai/frontend/web/src/features/nodes/hooks/useIsValidConnection.ts @@ -1,93 +1,94 @@ -import { useCallback } from 'react'; -import { Connection, Node, useReactFlow } from 'reactflow'; -import graphlib from '@dagrejs/graphlib'; -import { InvocationValue } from '../types/types'; +// TODO: enable this at some point +// import graphlib from '@dagrejs/graphlib'; +// import { useCallback } from 'react'; +// import { Connection, Node, useReactFlow } from 'reactflow'; +// import { InvocationValue } from '../types/types'; -export const useIsValidConnection = () => { - const flow = useReactFlow(); +// export const useIsValidConnection = () => { +// const flow = useReactFlow(); - // Check if an in-progress connection is valid - const isValidConnection = useCallback( - ({ source, sourceHandle, target, targetHandle }: Connection): boolean => { - const edges = flow.getEdges(); - const nodes = flow.getNodes(); +// // Check if an in-progress connection is valid +// const isValidConnection = useCallback( +// ({ source, sourceHandle, target, targetHandle }: Connection): boolean => { +// const edges = flow.getEdges(); +// const nodes = flow.getNodes(); - return true; +// // Connection must have valid targets +// if (!(source && sourceHandle && target && targetHandle)) { +// return false; +// } - // // Connection must have valid targets - // if (!(source && sourceHandle && target && targetHandle)) { - // return false; - // } +// // Connection is invalid if target already has a connection +// if ( +// edges.find((edge) => { +// return edge.target === target && edge.targetHandle === targetHandle; +// }) +// ) { +// return false; +// } - // // Connection is invalid if target already has a connection - // if ( - // edges.find((edge) => { - // return edge.target === target && edge.targetHandle === targetHandle; - // }) - // ) { - // return false; - // } +// // Find the source and target nodes +// const sourceNode = flow.getNode(source) as Node; - // // Find the source and target nodes - // const sourceNode = flow.getNode(source) as Node; +// const targetNode = flow.getNode(target) as Node; - // const targetNode = flow.getNode(target) as Node; +// // Conditional guards against undefined nodes/handles +// if (!(sourceNode && targetNode && sourceNode.data && targetNode.data)) { +// return false; +// } - // // Conditional guards against undefined nodes/handles - // if (!(sourceNode && targetNode && sourceNode.data && targetNode.data)) { - // return false; - // } +// // Connection types must be the same for a connection +// if ( +// sourceNode.data.outputs[sourceHandle].type !== +// targetNode.data.inputs[targetHandle].type +// ) { +// return false; +// } - // // Connection types must be the same for a connection - // if ( - // sourceNode.data.outputs[sourceHandle].type !== - // targetNode.data.inputs[targetHandle].type - // ) { - // return false; - // } +// // Graphs much be acyclic (no loops!) - // // Graphs much be acyclic (no loops!) +// /** +// * TODO: use `graphlib.alg.findCycles()` to identify strong connections +// * +// * this validation func only runs when the cursor hits the second handle of the connection, +// * and only on that second handle - so it cannot tell us exhaustively which connections +// * are valid. +// * +// * ideally, we check when the connection starts to calculate all invalid handles at once. +// * +// * requires making a new graphlib graph - and calling `findCycles()` - for each potential +// * handle. instead of using the `isValidConnection` prop, it would use the `onConnectStart` +// * prop. +// * +// * the strong connections should be stored in global state. +// * +// * then, `isValidConnection` would simple loop through the strong connections and if the +// * source and target are in a single strong connection, return false. +// * +// * and also, we can use this knowledge to style every handle when a connection starts, +// * which is otherwise not possible. +// */ - // /** - // * TODO: use `graphlib.alg.findCycles()` to identify strong connections - // * - // * this validation func only runs when the cursor hits the second handle of the connection, - // * and only on that second handle - so it cannot tell us exhaustively which connections - // * are valid. - // * - // * ideally, we check when the connection starts to calculate all invalid handles at once. - // * - // * requires making a new graphlib graph - and calling `findCycles()` - for each potential - // * handle. instead of using the `isValidConnection` prop, it would use the `onConnectStart` - // * prop. - // * - // * the strong connections should be stored in global state. - // * - // * then, `isValidConnection` would simple loop through the strong connections and if the - // * source and target are in a single strong connection, return false. - // * - // * and also, we can use this knowledge to style every handle when a connection starts, - // * which is otherwise not possible. - // */ +// // build a graphlib graph +// const g = new graphlib.Graph(); - // // build a graphlib graph - // const g = new graphlib.Graph(); +// nodes.forEach((n) => { +// g.setNode(n.id); +// }); - // nodes.forEach((n) => { - // g.setNode(n.id); - // }); +// edges.forEach((e) => { +// g.setEdge(e.source, e.target); +// }); - // edges.forEach((e) => { - // g.setEdge(e.source, e.target); - // }); +// // Add the candidate edge to the graph +// g.setEdge(source, target); - // // Add the candidate edge to the graph - // g.setEdge(source, target); +// return graphlib.alg.isAcyclic(g); +// }, +// [flow] +// ); - // return graphlib.alg.isAcyclic(g); - }, - [flow] - ); +// return isValidConnection; +// }; - return isValidConnection; -}; +export const useIsValidConnection = () => () => true; diff --git a/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts b/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts index eaa7fe66fc..9c01deded6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts +++ b/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts @@ -417,14 +417,17 @@ export const getFieldType = ( // if schemaObject has no type, then it should have one of allOf, anyOf, oneOf if (schemaObject.allOf) { rawFieldType = refObjectToFieldType( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion schemaObject.allOf![0] as OpenAPIV3.ReferenceObject ); } else if (schemaObject.anyOf) { rawFieldType = refObjectToFieldType( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion schemaObject.anyOf![0] as OpenAPIV3.ReferenceObject ); } else if (schemaObject.oneOf) { rawFieldType = refObjectToFieldType( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion schemaObject.oneOf![0] as OpenAPIV3.ReferenceObject ); } @@ -547,6 +550,7 @@ export const buildOutputFieldTemplates = ( const outputSchemaName = refObject.$ref.split('/').slice(-1)[0]; // get the output schema itself + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const outputSchema = openAPI.components!.schemas![outputSchemaName]; if (isSchemaObject(outputSchema)) { diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts index 64d579ce8b..bae29ee3f5 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildNodesGraph.ts @@ -37,7 +37,7 @@ export const buildNodesGraph = (state: RootState): Graph => { // Reduce the node editor nodes into invocation graph nodes const parsedNodes = filteredNodes.reduce>( - (nodesAccumulator, node, nodeIndex) => { + (nodesAccumulator, node) => { const { id, data } = node; const { type, inputs } = data; @@ -50,7 +50,7 @@ export const buildNodesGraph = (state: RootState): Graph => { return inputsAccumulator; }, - {} as Record, any> + {} as Record, unknown> ); // Build this specific node @@ -72,7 +72,7 @@ export const buildNodesGraph = (state: RootState): Graph => { // Reduce the node editor edges into invocation graph edges const parsedEdges = edges.reduce>( - (edgesAccumulator, edge, edgeIndex) => { + (edgesAccumulator, edge) => { const { source, target, sourceHandle, targetHandle } = edge; // Format the edges and add to the edges array diff --git a/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts b/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts index ee751f0b16..bedf932b50 100644 --- a/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts +++ b/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts @@ -24,6 +24,7 @@ const invocationDenylist = [ export const parseSchema = (openAPI: OpenAPIV3.Document) => { // filter out non-invocation schemas, plus some tricky invocations for now const filteredSchemas = filter( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion openAPI.components!.schemas, (schema, key) => key.includes('Invocation') && @@ -102,6 +103,7 @@ export const parseSchema = (openAPI: OpenAPIV3.Document) => { // some special handling is needed for collect, iterate and range nodes if (type === 'iterate') { // this is guaranteed to be a SchemaObject + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const iterationOutput = openAPI.components!.schemas![ 'IterateInvocationOutput' ] as OpenAPIV3.SchemaObject; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx index 99ab512948..418ed9278f 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse.tsx @@ -15,7 +15,6 @@ import { getValidControlNets } from 'features/controlNet/util/getValidControlNet import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { map } from 'lodash-es'; import { Fragment, memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; import { FaPlus } from 'react-icons/fa'; import { useGetControlNetModelsQuery } from 'services/api/endpoints/models'; import { v4 as uuidv4 } from 'uuid'; @@ -38,7 +37,6 @@ const selector = createSelector( ); const ParamControlNetCollapse = () => { - const { t } = useTranslation(); const { controlNetsArray, activeLabel } = useAppSelector(selector); const isControlNetDisabled = useFeatureStatus('controlNet').isFeatureDisabled; const dispatch = useAppDispatch(); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx index 55daadf9ea..895b6cedbf 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx @@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'; const selector = createSelector( [stateSelector], - ({ generation, hotkeys, config, ui }) => { + ({ generation, hotkeys, config }) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.width; const { width, aspectRatio } = generation; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImage.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImage.tsx index c95149393e..0c5b2c68d0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImage.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImage.tsx @@ -27,12 +27,9 @@ const selector = createSelector( const InitialImage = () => { const { initialImage } = useAppSelector(selector); - const { - currentData: imageDTO, - isLoading, - isError, - isSuccess, - } = useGetImageDTOQuery(initialImage?.imageName ?? skipToken); + const { currentData: imageDTO } = useGetImageDTOQuery( + initialImage?.imageName ?? skipToken + ); const draggableData = useMemo(() => { if (imageDTO) { diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx index 5d0ea077c1..45fd7fcf57 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamCpuNoise.tsx @@ -5,7 +5,6 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISwitch from 'common/components/IAISwitch'; import { shouldUseCpuNoiseChanged } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; -import { useTranslation } from 'react-i18next'; const selector = createSelector( stateSelector, @@ -23,8 +22,6 @@ export const ParamCpuNoiseToggle = () => { const dispatch = useAppDispatch(); const { isDisabled, shouldUseCpuNoise } = useAppSelector(selector); - const { t } = useTranslation(); - const handleChange = (e: ChangeEvent) => dispatch(shouldUseCpuNoiseChanged(e.target.checked)); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamNoiseToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamNoiseToggle.tsx index 9c8b96af65..c1c2fb5119 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamNoiseToggle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Noise/ParamNoiseToggle.tsx @@ -3,7 +3,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldUseNoiseSettings } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; -import { useTranslation } from 'react-i18next'; export const ParamNoiseToggle = () => { const dispatch = useAppDispatch(); @@ -12,8 +11,6 @@ export const ParamNoiseToggle = () => { (state: RootState) => state.generation.shouldUseNoiseSettings ); - const { t } = useTranslation(); - const handleChange = (e: ChangeEvent) => dispatch(setShouldUseNoiseSettings(e.target.checked)); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Upscale/ParamRealESRGANModel.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Upscale/ParamRealESRGANModel.tsx index 563165105b..5c1bc09717 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Upscale/ParamRealESRGANModel.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Upscale/ParamRealESRGANModel.tsx @@ -7,7 +7,6 @@ import { ESRGANModelName, esrganModelNameChanged, } from 'features/parameters/store/postprocessingSlice'; -import { useTranslation } from 'react-i18next'; export const ESRGAN_MODEL_NAMES: SelectItem[] = [ { diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationToggle.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationToggle.tsx index 1c05468de0..96929ea00a 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationToggle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Variations/ParamVariationToggle.tsx @@ -3,7 +3,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISwitch from 'common/components/IAISwitch'; import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice'; import { ChangeEvent } from 'react'; -import { useTranslation } from 'react-i18next'; export const ParamVariationToggle = () => { const dispatch = useAppDispatch(); @@ -12,8 +11,6 @@ export const ParamVariationToggle = () => { (state: RootState) => state.generation.shouldGenerateVariations ); - const { t } = useTranslation(); - const handleChange = (e: ChangeEvent) => dispatch(setShouldGenerateVariations(e.target.checked)); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/AspectRatioPreview.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/AspectRatioPreview.tsx deleted file mode 100644 index ecf4a6713e..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/AspectRatioPreview.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { Flex, Text } from '@chakra-ui/react'; -import { memo, useMemo } from 'react'; - -export const ratioToCSSString = ( - ratio: AspectRatio, - orientation: Orientation -) => { - if (orientation === 'portrait') { - return `${ratio[0]}/${ratio[1]}`; - } - return `${ratio[1]}/${ratio[0]}`; -}; - -export const ratioToDisplayString = ( - ratio: AspectRatio, - orientation: Orientation -) => { - if (orientation === 'portrait') { - return `${ratio[0]}:${ratio[1]}`; - } - return `${ratio[1]}:${ratio[0]}`; -}; - -type AspectRatioPreviewProps = { - ratio: AspectRatio; - orientation: Orientation; - size: string; -}; - -export type AspectRatio = [number, number]; - -export type Orientation = 'portrait' | 'landscape'; - -const AspectRatioPreview = (props: AspectRatioPreviewProps) => { - const { ratio, size, orientation } = props; - - const ratioCSSString = useMemo(() => { - if (orientation === 'portrait') { - return `${ratio[0]}/${ratio[1]}`; - } - return `${ratio[1]}/${ratio[0]}`; - }, [ratio, orientation]); - - const ratioDisplayString = useMemo(() => `${ratio[0]}:${ratio[1]}`, [ratio]); - - return ( - - - - {ratioDisplayString} - - - - ); -}; - -export default memo(AspectRatioPreview); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/DimensionsSettings.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/DimensionsSettings.tsx deleted file mode 100644 index a187eecd83..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/_ImageDimensions/DimensionsSettings.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { Box, Flex, FormControl, FormLabel, Select } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAISlider from 'common/components/IAISlider'; -import { setWidth } from 'features/parameters/store/generationSlice'; -import { memo, useState } from 'react'; -import AspectRatioPreview, { - AspectRatio, - Orientation, -} from './AspectRatioPreview'; - -const RATIOS: AspectRatio[] = [ - [1, 1], - [5, 4], - [3, 2], - [16, 10], - [16, 9], -]; - -RATIOS.forEach((r) => { - const float = r[0] / r[1]; - console.log((512 * float) / 8); -}); - -const dimensionsSettingsSelector = createSelector( - (state: RootState) => state.generation, - (generation) => { - const { width, height } = generation; - - return { width, height }; - } -); - -const DimensionsSettings = () => { - const { width, height } = useAppSelector(dimensionsSettingsSelector); - const dispatch = useAppDispatch(); - const [ratioIndex, setRatioIndex] = useState(4); - const [orientation, setOrientation] = useState('portrait'); - - return ( - - - - - - Aspect Ratio - - - { - dispatch(setWidth(v)); - }} - /> - - ); -}; - -export default memo(DimensionsSettings); diff --git a/invokeai/frontend/web/src/features/parameters/hooks/useRecallParameters.ts b/invokeai/frontend/web/src/features/parameters/hooks/useRecallParameters.ts index a0522c2150..e19f4cd5f4 100644 --- a/invokeai/frontend/web/src/features/parameters/hooks/useRecallParameters.ts +++ b/invokeai/frontend/web/src/features/parameters/hooks/useRecallParameters.ts @@ -3,7 +3,6 @@ import { useAppDispatch } from 'app/store/storeHooks'; import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { UnsafeImageMetadata } from 'services/api/endpoints/images'; -import { isImageField } from 'services/api/guards'; import { ImageDTO } from 'services/api/types'; import { initialImageSelected, modelSelected } from '../store/actions'; import { diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 9a1d514a49..971558335b 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -266,7 +266,7 @@ export const generationSlice = createSlice({ const defaultModel = action.payload.sd?.defaultModel; if (defaultModel && !state.model) { - const [base_model, model_type, model_name] = defaultModel.split('/'); + const [base_model, _model_type, model_name] = defaultModel.split('/'); const result = zMainModel.safeParse({ model_name, diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts index 1da3325c09..30e6fdcd3d 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToControlNetModelParam.ts @@ -6,7 +6,7 @@ export const modelIdToControlNetModelParam = ( controlNetModelId: string ): ControlNetModelField | undefined => { const log = logger('models'); - const [base_model, model_type, model_name] = controlNetModelId.split('/'); + const [base_model, _model_type, model_name] = controlNetModelId.split('/'); const result = zControlNetModel.safeParse({ base_model, diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts index ca8bd36e24..bf4c6454fb 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToLoRAModelParam.ts @@ -6,7 +6,7 @@ export const modelIdToLoRAModelParam = ( ): LoRAModelParam | undefined => { const log = logger('models'); - const [base_model, model_type, model_name] = loraModelId.split('/'); + const [base_model, _model_type, model_name] = loraModelId.split('/'); const result = zLoRAModel.safeParse({ base_model, diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts index 1468d9595e..1b8cbbfe72 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToMainModelParam.ts @@ -8,7 +8,7 @@ export const modelIdToMainModelParam = ( mainModelId: string ): MainModelParam | undefined => { const log = logger('models'); - const [base_model, model_type, model_name] = mainModelId.split('/'); + const [base_model, _model_type, model_name] = mainModelId.split('/'); const result = zMainModel.safeParse({ base_model, diff --git a/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts b/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts index 1d60ab1c84..1f3908dd47 100644 --- a/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts +++ b/invokeai/frontend/web/src/features/parameters/util/modelIdToVAEModelParam.ts @@ -5,7 +5,7 @@ export const modelIdToVAEModelParam = ( vaeModelId: string ): VaeModelParam | undefined => { const log = logger('models'); - const [base_model, model_type, model_name] = vaeModelId.split('/'); + const [base_model, _model_type, model_name] = vaeModelId.split('/'); const result = zVaeModel.safeParse({ base_model, diff --git a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx index c5945140c3..767b394ac1 100644 --- a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx +++ b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx @@ -1,15 +1,14 @@ import { Flex, Icon, Text } from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; -import { isEqual } from 'lodash-es'; -import { useTranslation } from 'react-i18next'; -import { systemSelector } from '../store/systemSelectors'; -import { ResourceKey } from 'i18next'; +import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { AnimatePresence, motion } from 'framer-motion'; +import { ResourceKey } from 'i18next'; import { useMemo, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; import { FaCircle } from 'react-icons/fa'; import { useHoverDirty } from 'react-use'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; +import { systemSelector } from '../store/systemSelectors'; const statusIndicatorSelector = createSelector( systemSelector, diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx index f327e10efc..c7c1182d21 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx @@ -5,7 +5,6 @@ import { PropsWithChildren, memo } from 'react'; import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants'; import { uiSelector } from '../store/uiSelectors'; import PinParametersPanelButton from './PinParametersPanelButton'; -import OverlayScrollable from './common/OverlayScrollable'; const selector = createSelector(uiSelector, (ui) => { const { shouldPinParametersPanel, shouldShowParametersPanel } = ui; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx index cda908da50..d343d17a47 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx @@ -19,18 +19,17 @@ const selector = createSelector( [uiSelector, generationSelector], (ui, generation) => { const { shouldUseSliders } = ui; - const { shouldFitToWidthHeight, shouldRandomizeSeed } = generation; + const { shouldRandomizeSeed } = generation; const activeLabel = !shouldRandomizeSeed ? 'Manual Seed' : undefined; - return { shouldUseSliders, shouldFitToWidthHeight, activeLabel }; + return { shouldUseSliders, activeLabel }; }, defaultSelectorOptions ); const ImageToImageTabCoreParameters = () => { - const { shouldUseSliders, shouldFitToWidthHeight, activeLabel } = - useAppSelector(selector); + const { shouldUseSliders, activeLabel } = useAppSelector(selector); return ( { socket.on('connect_error', (error) => { if (error && error.message) { - const data: string | undefined = (error as any).data; + const data: string | undefined = ( + error as unknown as { data: string | undefined } + ).data; if (data === 'ERR_UNAUTHENTICATED') { dispatch( addToast( diff --git a/invokeai/frontend/web/src/theme/components/button.ts b/invokeai/frontend/web/src/theme/components/button.ts index dd27a69a71..c01d564494 100644 --- a/invokeai/frontend/web/src/theme/components/button.ts +++ b/invokeai/frontend/web/src/theme/components/button.ts @@ -71,9 +71,13 @@ const invokeAIOutline = defineStyle((props) => { border: '1px solid', borderColor: c === 'gray' ? borderColor : 'currentColor', '.chakra-button__group[data-attached][data-orientation=horizontal] > &:not(:last-of-type)': - { marginEnd: '-1px' }, + { + marginEnd: '-1px', + }, '.chakra-button__group[data-attached][data-orientation=vertical] > &:not(:last-of-type)': - { marginBottom: '-1px' }, + { + marginBottom: '-1px', + }, }; }); diff --git a/invokeai/frontend/web/src/theme/components/modal.ts b/invokeai/frontend/web/src/theme/components/modal.ts index 8310d9d46c..54e3a347f4 100644 --- a/invokeai/frontend/web/src/theme/components/modal.ts +++ b/invokeai/frontend/web/src/theme/components/modal.ts @@ -14,14 +14,14 @@ const invokeAIOverlay = defineStyle((props) => ({ const invokeAIDialogContainer = defineStyle({}); -const invokeAIDialog = defineStyle((props) => { +const invokeAIDialog = defineStyle(() => { return { layerStyle: 'first', maxH: '80vh', }; }); -const invokeAIHeader = defineStyle((props) => { +const invokeAIHeader = defineStyle(() => { return { fontWeight: '600', fontSize: 'lg', @@ -42,8 +42,8 @@ const invokeAIFooter = defineStyle({}); export const invokeAI = definePartsStyle((props) => ({ overlay: invokeAIOverlay(props), dialogContainer: invokeAIDialogContainer, - dialog: invokeAIDialog(props), - header: invokeAIHeader(props), + dialog: invokeAIDialog(), + header: invokeAIHeader(), closeButton: invokeAICloseButton, body: invokeAIBody, footer: invokeAIFooter,