diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py index 63db3d925c..1d7f218bfc 100644 --- a/invokeai/app/invocations/latent.py +++ b/invokeai/app/invocations/latent.py @@ -543,6 +543,7 @@ class LatentsToImageInvocation(BaseInvocation): image_category=ImageCategory.GENERAL, node_id=self.id, session_id=context.graph_execution_state_id, + is_intermediate=self.is_intermediate ) return ImageOutput( diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index c072a9d95c..dd44782413 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -23,8 +23,7 @@ "dev": "concurrently \"vite dev\" \"yarn run theme:watch\"", "dev:host": "concurrently \"vite dev --host\" \"yarn run theme:watch\"", "build": "yarn run lint && vite build", - "api:web": "openapi -i http://localhost:9090/openapi.json -o src/services/api --client axios --useOptions --useUnionTypes --indent 2 --request src/services/fixtures/request.ts", - "api:file": "openapi -i src/services/fixtures/openapi.json -o src/services/api --client axios --useOptions --useUnionTypes --indent 2 --request src/services/fixtures/request.ts", + "typegen": "npx openapi-typescript http://localhost:9090/openapi.json --output src/services/schema.d.ts -t", "preview": "vite preview", "lint:madge": "madge --circular src/main.tsx", "lint:eslint": "eslint --max-warnings=0 .", @@ -81,9 +80,12 @@ "i18next-http-backend": "^2.2.0", "konva": "^9.0.1", "lodash-es": "^4.17.21", + "nanostores": "^0.9.2", + "openapi-fetch": "^0.4.0", "overlayscrollbars": "^2.1.1", "overlayscrollbars-react": "^0.5.0", "patch-package": "^7.0.0", + "query-string": "^8.1.0", "re-resizable": "^6.9.9", "react": "^18.2.0", "react-colorful": "^5.6.1", @@ -140,6 +142,7 @@ "lint-staged": "^13.2.2", "madge": "^6.0.0", "openapi-types": "^12.1.0", + "openapi-typescript": "^6.2.8", "openapi-typescript-codegen": "^0.24.0", "postinstall-postinstall": "^2.1.0", "prettier": "^2.8.8", diff --git a/invokeai/frontend/web/patches/openapi-fetch+0.4.0.patch b/invokeai/frontend/web/patches/openapi-fetch+0.4.0.patch new file mode 100644 index 0000000000..d82843f71c --- /dev/null +++ b/invokeai/frontend/web/patches/openapi-fetch+0.4.0.patch @@ -0,0 +1,55 @@ +diff --git a/node_modules/openapi-fetch/dist/index.js b/node_modules/openapi-fetch/dist/index.js +index cd4528a..8976b51 100644 +--- a/node_modules/openapi-fetch/dist/index.js ++++ b/node_modules/openapi-fetch/dist/index.js +@@ -1,5 +1,5 @@ + // settings & const +-const DEFAULT_HEADERS = { ++const CONTENT_TYPE_APPLICATION_JSON = { + "Content-Type": "application/json", + }; + const TRAILING_SLASH_RE = /\/*$/; +@@ -29,18 +29,29 @@ export function createFinalURL(url, options) { + } + return finalURL; + } ++function stringifyBody(body) { ++ if (body instanceof ArrayBuffer || body instanceof File || body instanceof DataView || body instanceof Blob || ArrayBuffer.isView(body) || body instanceof URLSearchParams || body instanceof FormData) { ++ return; ++ } ++ ++ if (typeof body === "string") { ++ return body; ++ } ++ ++ return JSON.stringify(body); ++ } ++ + export default function createClient(clientOptions = {}) { + const { fetch = globalThis.fetch, ...options } = clientOptions; +- const defaultHeaders = new Headers({ +- ...DEFAULT_HEADERS, +- ...(options.headers ?? {}), +- }); ++ const defaultHeaders = new Headers(options.headers ?? {}); + async function coreFetch(url, fetchOptions) { + const { headers, body: requestBody, params = {}, parseAs = "json", querySerializer = defaultSerializer, ...init } = fetchOptions || {}; + // URL + const finalURL = createFinalURL(url, { baseUrl: options.baseUrl, params, querySerializer }); ++ // Stringify body if needed ++ const stringifiedBody = stringifyBody(requestBody); + // headers +- const baseHeaders = new Headers(defaultHeaders); // clone defaults (don’t overwrite!) ++ const baseHeaders = new Headers(stringifiedBody ? { ...CONTENT_TYPE_APPLICATION_JSON, ...defaultHeaders } : defaultHeaders); // clone defaults (don’t overwrite!) + const headerOverrides = new Headers(headers); + for (const [k, v] of headerOverrides.entries()) { + if (v === undefined || v === null) +@@ -54,7 +65,7 @@ export default function createClient(clientOptions = {}) { + ...options, + ...init, + headers: baseHeaders, +- body: typeof requestBody === "string" ? requestBody : JSON.stringify(requestBody), ++ body: stringifiedBody ?? requestBody, + }); + // handle empty content + // note: we return `{}` because we want user truthy checks for `.data` or `.error` to succeed diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 55fcc97745..3f1f2cf7a6 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -24,7 +24,7 @@ import Toaster from './Toaster'; import DeleteImageModal from 'features/gallery/components/DeleteImageModal'; import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal'; -import { useListModelsQuery } from 'services/apiSlice'; +import { useListModelsQuery } from 'services/api/endpoints/models'; const DEFAULT_CONFIG = {}; diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx index 104073c023..6150259f66 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx @@ -11,8 +11,8 @@ import { } from '@dnd-kit/core'; import { PropsWithChildren, memo, useCallback, useState } from 'react'; import OverlayDragImage from './OverlayDragImage'; -import { ImageDTO } from 'services/api'; -import { isImageDTO } from 'services/types/guards'; +import { ImageDTO } from 'services/api/types'; +import { isImageDTO } from 'services/api/guards'; import { snapCenterToCursor } from '@dnd-kit/modifiers'; import { AnimatePresence, motion } from 'framer-motion'; diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx index 510dadc823..611d1ceee9 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx @@ -1,6 +1,6 @@ import { Box, Image } from '@chakra-ui/react'; import { memo } from 'react'; -import { ImageDTO } from 'services/api'; +import { ImageDTO } from 'services/api/types'; type OverlayDragImageProps = { image: ImageDTO; diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index 141e62652d..4d83a407c0 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -7,7 +7,7 @@ import React, { } from 'react'; import { Provider } from 'react-redux'; import { store } from 'app/store/store'; -import { OpenAPI } from 'services/api'; +// import { OpenAPI } from 'services/api/types'; import Loading from '../../common/components/Loading/Loading'; import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares'; @@ -23,6 +23,7 @@ import { } from 'app/contexts/DeleteImageContext'; import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal'; import { AddImageToBoardContextProvider } from '../contexts/AddImageToBoardContext'; +import { $authToken, $baseUrl } from 'services/api/client'; const App = lazy(() => import('./App')); const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider')); @@ -47,12 +48,12 @@ const InvokeAIUI = ({ useEffect(() => { // configure API client token if (token) { - OpenAPI.TOKEN = token; + $authToken.set(token); } // configure API client base url if (apiUrl) { - OpenAPI.BASE = apiUrl; + $baseUrl.set(apiUrl); } // reset dynamically added middlewares @@ -69,6 +70,12 @@ const InvokeAIUI = ({ } else { addMiddleware(socketMiddleware()); } + + return () => { + // Reset the API client token and base url on unmount + $baseUrl.set(undefined); + $authToken.set(undefined); + }; }, [apiUrl, token, middleware]); return ( diff --git a/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx b/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx index f5a856d3d8..f37f06d4b1 100644 --- a/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx +++ b/invokeai/frontend/web/src/app/contexts/AddImageToBoardContext.tsx @@ -1,7 +1,7 @@ import { useDisclosure } from '@chakra-ui/react'; import { PropsWithChildren, createContext, useCallback, useState } from 'react'; -import { ImageDTO } from 'services/api'; -import { useAddImageToBoardMutation } from 'services/apiSlice'; +import { ImageDTO } from 'services/api/types'; +import { useAddImageToBoardMutation } from 'services/api/endpoints/boardImages'; export type ImageUsage = { isInitialImage: boolean; diff --git a/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx b/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx index d01298944b..b59649a5f8 100644 --- a/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx +++ b/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx @@ -11,7 +11,7 @@ import { useEffect, useState, } from 'react'; -import { ImageDTO } from 'services/api'; +import { ImageDTO } from 'services/api/types'; import { RootState } from 'app/store/store'; import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { controlNetSelector } from 'features/controlNet/store/controlNetSlice'; diff --git a/invokeai/frontend/web/src/app/store/middleware/devtools/actionSanitizer.ts b/invokeai/frontend/web/src/app/store/middleware/devtools/actionSanitizer.ts index 24b85e0f83..227b15d6f8 100644 --- a/invokeai/frontend/web/src/app/store/middleware/devtools/actionSanitizer.ts +++ b/invokeai/frontend/web/src/app/store/middleware/devtools/actionSanitizer.ts @@ -1,7 +1,7 @@ import { AnyAction } from '@reduxjs/toolkit'; import { isAnyGraphBuilt } from 'features/nodes/store/actions'; import { forEach } from 'lodash-es'; -import { Graph } from 'services/api'; +import { Graph } from 'services/api/types'; export const actionSanitizer = (action: A): A => { if (isAnyGraphBuilt(action)) { 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 90f71879a1..322cc51fa7 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,7 +1,7 @@ import { startAppListening } from '..'; import { log } from 'app/logging/useLogger'; import { commitStagingAreaImage } from 'features/canvas/store/canvasSlice'; -import { sessionCanceled } from 'services/thunks/session'; +import { sessionCanceled } from 'services/api/thunks/session'; const moduleLog = log.child({ namespace: 'canvas' }); @@ -10,7 +10,7 @@ export const addCommitStagingAreaImageListener = () => { actionCreator: commitStagingAreaImage, effect: async (action, { dispatch, getState }) => { const state = getState(); - const { sessionId, isProcessing } = state.system; + const { sessionId: session_id, isProcessing } = state.system; const canvasSessionId = action.payload; if (!isProcessing) { @@ -23,12 +23,12 @@ export const addCommitStagingAreaImageListener = () => { return; } - if (canvasSessionId !== sessionId) { + if (canvasSessionId !== session_id) { moduleLog.debug( { data: { canvasSessionId, - sessionId, + session_id, }, }, 'Canvas session does not match global session, skipping cancel' @@ -36,7 +36,7 @@ export const addCommitStagingAreaImageListener = () => { return; } - dispatch(sessionCanceled({ sessionId })); + dispatch(sessionCanceled({ session_id })); }, }); }; 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 eab4389ceb..1c96c5700d 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 @@ -2,9 +2,12 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; import { boardIdSelected } from 'features/gallery/store/boardSlice'; import { selectImagesAll } from 'features/gallery/store/imagesSlice'; -import { IMAGES_PER_PAGE, receivedPageOfImages } from 'services/thunks/image'; -import { api } from 'services/apiSlice'; +import { + IMAGES_PER_PAGE, + receivedPageOfImages, +} from 'services/api/thunks/image'; import { imageSelected } from 'features/gallery/store/gallerySlice'; +import { boardsApi } from 'services/api/endpoints/boards'; const moduleLog = log.child({ namespace: 'boards' }); @@ -12,14 +15,14 @@ export const addBoardIdSelectedListener = () => { startAppListening({ actionCreator: boardIdSelected, effect: (action, { getState, dispatch }) => { - const boardId = action.payload; + const board_id = action.payload; // we need to check if we need to fetch more images const state = getState(); const allImages = selectImagesAll(state); - if (!boardId) { + if (!board_id) { // a board was unselected dispatch(imageSelected(allImages[0]?.image_name)); return; @@ -29,13 +32,14 @@ export const addBoardIdSelectedListener = () => { const filteredImages = allImages.filter((i) => { const isInCategory = categories.includes(i.image_category); - const isInSelectedBoard = boardId ? i.board_id === boardId : true; + const isInSelectedBoard = board_id ? i.board_id === board_id : true; return isInCategory && isInSelectedBoard; }); // get the board from the cache - const { data: boards } = api.endpoints.listAllBoards.select()(state); - const board = boards?.find((b) => b.board_id === boardId); + const { data: boards } = + boardsApi.endpoints.listAllBoards.select()(state); + const board = boards?.find((b) => b.board_id === board_id); if (!board) { // can't find the board in cache... @@ -50,7 +54,9 @@ export const addBoardIdSelectedListener = () => { filteredImages.length < board.image_count && filteredImages.length < IMAGES_PER_PAGE ) { - dispatch(receivedPageOfImages({ categories, boardId })); + dispatch( + receivedPageOfImages({ categories, board_id, is_intermediate: false }) + ); } }, }); @@ -60,13 +66,13 @@ export const addBoardIdSelected_changeSelectedImage_listener = () => { startAppListening({ actionCreator: boardIdSelected, effect: (action, { getState, dispatch }) => { - const boardId = action.payload; + const board_id = action.payload; const state = getState(); // we need to check if we need to fetch more images - if (!boardId) { + if (!board_id) { // a board was unselected - we don't need to do anything return; } @@ -75,13 +81,14 @@ export const addBoardIdSelected_changeSelectedImage_listener = () => { const filteredImages = selectImagesAll(state).filter((i) => { const isInCategory = categories.includes(i.image_category); - const isInSelectedBoard = boardId ? i.board_id === boardId : true; + const isInSelectedBoard = board_id ? i.board_id === board_id : true; return isInCategory && isInSelectedBoard; }); // get the board from the cache - const { data: boards } = api.endpoints.listAllBoards.select()(state); - const board = boards?.find((b) => b.board_id === boardId); + const { data: boards } = + boardsApi.endpoints.listAllBoards.select()(state); + const board = boards?.find((b) => b.board_id === board_id); if (!board) { // can't find the board in cache... return; @@ -92,7 +99,9 @@ export const addBoardIdSelected_changeSelectedImage_listener = () => { filteredImages.length < board.image_count && filteredImages.length < IMAGES_PER_PAGE ) { - dispatch(receivedPageOfImages({ categories, boardId })); + dispatch( + receivedPageOfImages({ categories, board_id, is_intermediate: false }) + ); } }, }); 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 dd77e66c67..ce135ab3d0 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 @@ -2,7 +2,7 @@ import { canvasMerged } from 'features/canvas/store/actions'; import { startAppListening } from '..'; import { log } from 'app/logging/useLogger'; import { addToast } from 'features/system/store/systemSlice'; -import { imageUploaded } from 'services/thunks/image'; +import { imageUploaded } from 'services/api/thunks/image'; import { setMergedCanvas } from 'features/canvas/store/canvasSlice'; import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider'; import { getFullBaseLayerBlob } from 'features/canvas/util/getFullBaseLayerBlob'; @@ -47,13 +47,11 @@ export const addCanvasMergedListener = () => { const imageUploadedRequest = dispatch( imageUploaded({ - formData: { - file: new File([blob], 'mergedCanvas.png', { - type: 'image/png', - }), - }, - imageCategory: 'general', - isIntermediate: true, + file: new File([blob], 'mergedCanvas.png', { + type: 'image/png', + }), + image_category: 'general', + is_intermediate: true, postUploadAction: { type: 'TOAST_CANVAS_MERGED', }, @@ -68,13 +66,13 @@ export const addCanvasMergedListener = () => { uploadedImageAction.meta.requestId === imageUploadedRequest.requestId ); - const mergedCanvasImage = payload; + const { image_name } = payload; dispatch( setMergedCanvas({ kind: 'image', layer: 'base', - image: mergedCanvasImage, + imageName: image_name, ...baseLayerRect, }) ); 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 b53b08cd27..af55a1382e 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,7 +1,7 @@ import { canvasSavedToGallery } from 'features/canvas/store/actions'; import { startAppListening } from '..'; import { log } from 'app/logging/useLogger'; -import { imageUploaded } from 'services/thunks/image'; +import { imageUploaded } from 'services/api/thunks/image'; import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob'; import { addToast } from 'features/system/store/systemSlice'; import { imageUpserted } from 'features/gallery/store/imagesSlice'; @@ -30,13 +30,11 @@ export const addCanvasSavedToGalleryListener = () => { const imageUploadedRequest = dispatch( imageUploaded({ - formData: { - file: new File([blob], 'savedCanvas.png', { - type: 'image/png', - }), - }, - imageCategory: 'general', - isIntermediate: false, + file: new File([blob], 'savedCanvas.png', { + type: 'image/png', + }), + image_category: 'general', + is_intermediate: false, postUploadAction: { type: 'TOAST_CANVAS_SAVED_TO_GALLERY', }, 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 7ff9a5118c..3e11a5f98b 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,14 +1,13 @@ import { startAppListening } from '..'; -import { imageMetadataReceived } from 'services/thunks/image'; +import { imageMetadataReceived } from 'services/api/thunks/image'; import { log } from 'app/logging/useLogger'; import { controlNetImageProcessed } from 'features/controlNet/store/actions'; -import { Graph } from 'services/api'; -import { sessionCreated } from 'services/thunks/session'; +import { Graph } from 'services/api/types'; +import { sessionCreated } from 'services/api/thunks/session'; import { sessionReadyToInvoke } from 'features/system/store/actions'; import { socketInvocationComplete } from 'services/events/actions'; -import { isImageOutput } from 'services/types/guards'; +import { isImageOutput } from 'services/api/guards'; import { controlNetProcessedImageChanged } from 'features/controlNet/store/controlNetSlice'; -import { pick } from 'lodash-es'; const moduleLog = log.child({ namespace: 'controlNet' }); 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 0f404cab68..082dfc0efb 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,13 +1,13 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { imageMetadataReceived } from 'services/thunks/image'; -import { api } from 'services/apiSlice'; +import { imageMetadataReceived } from 'services/api/thunks/image'; +import { boardImagesApi } from 'services/api/endpoints/boardImages'; const moduleLog = log.child({ namespace: 'boards' }); export const addImageAddedToBoardFulfilledListener = () => { startAppListening({ - matcher: api.endpoints.addImageToBoard.matchFulfilled, + matcher: boardImagesApi.endpoints.addImageToBoard.matchFulfilled, effect: (action, { getState, dispatch }) => { const { board_id, image_name } = action.meta.arg.originalArgs; @@ -18,7 +18,7 @@ export const addImageAddedToBoardFulfilledListener = () => { dispatch( imageMetadataReceived({ - imageName: image_name, + image_name, }) ); }, @@ -27,7 +27,7 @@ export const addImageAddedToBoardFulfilledListener = () => { export const addImageAddedToBoardRejectedListener = () => { startAppListening({ - matcher: api.endpoints.addImageToBoard.matchRejected, + matcher: boardImagesApi.endpoints.addImageToBoard.matchRejected, effect: (action, { getState, dispatch }) => { const { board_id, image_name } = action.meta.arg.originalArgs; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts index 8f01b8d7b8..25b7b7c11f 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts @@ -1,6 +1,6 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { receivedPageOfImages } from 'services/thunks/image'; +import { receivedPageOfImages } from 'services/api/thunks/image'; import { imageCategoriesChanged, selectFilteredImagesAsArray, @@ -19,7 +19,8 @@ export const addImageCategoriesChangedListener = () => { dispatch( receivedPageOfImages({ categories: action.payload, - boardId: state.boards.selectedBoardId, + board_id: state.boards.selectedBoardId, + is_intermediate: false, }) ); } 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 224aa0d2aa..91cd509ca6 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,6 +1,6 @@ import { requestedImageDeletion } from 'features/gallery/store/actions'; import { startAppListening } from '..'; -import { imageDeleted } from 'services/thunks/image'; +import { imageDeleted } from 'services/api/thunks/image'; import { log } from 'app/logging/useLogger'; import { clamp } from 'lodash-es'; import { imageSelected } from 'features/gallery/store/gallerySlice'; @@ -12,7 +12,7 @@ import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; -import { api } from 'services/apiSlice'; +import { api } from 'services/api'; const moduleLog = log.child({ namespace: 'image' }); @@ -76,7 +76,7 @@ export const addRequestedImageDeletionListener = () => { dispatch(imageRemoved(image_name)); // Delete from server - const { requestId } = dispatch(imageDeleted({ imageName: image_name })); + const { requestId } = dispatch(imageDeleted({ image_name })); // Wait for successful deletion, then trigger boards to re-fetch const wasImageDeleted = await condition( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts index ed308f08a8..24265faaa9 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts @@ -1,6 +1,6 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { imageMetadataReceived, imageUpdated } from 'services/thunks/image'; +import { imageMetadataReceived, imageUpdated } from 'services/api/thunks/image'; import { imageUpserted } from 'features/gallery/store/imagesSlice'; const moduleLog = log.child({ namespace: 'image' }); @@ -19,8 +19,8 @@ export const addImageMetadataReceivedFulfilledListener = () => { ) { dispatch( imageUpdated({ - imageName: image.image_name, - requestBody: { is_intermediate: false }, + image_name: image.image_name, + is_intermediate: image.is_intermediate, }) ); } else if (image.is_intermediate) { 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 40847ade3a..5c056474e3 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,13 +1,13 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { imageMetadataReceived } from 'services/thunks/image'; -import { api } from 'services/apiSlice'; +import { imageMetadataReceived } from 'services/api/thunks/image'; +import { boardImagesApi } from 'services/api/endpoints/boardImages'; const moduleLog = log.child({ namespace: 'boards' }); export const addImageRemovedFromBoardFulfilledListener = () => { startAppListening({ - matcher: api.endpoints.removeImageFromBoard.matchFulfilled, + matcher: boardImagesApi.endpoints.removeImageFromBoard.matchFulfilled, effect: (action, { getState, dispatch }) => { const { board_id, image_name } = action.meta.arg.originalArgs; @@ -18,7 +18,7 @@ export const addImageRemovedFromBoardFulfilledListener = () => { dispatch( imageMetadataReceived({ - imageName: image_name, + image_name, }) ); }, @@ -27,7 +27,7 @@ export const addImageRemovedFromBoardFulfilledListener = () => { export const addImageRemovedFromBoardRejectedListener = () => { startAppListening({ - matcher: api.endpoints.removeImageFromBoard.matchRejected, + matcher: boardImagesApi.endpoints.removeImageFromBoard.matchRejected, effect: (action, { getState, dispatch }) => { const { board_id, image_name } = action.meta.arg.originalArgs; 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 index 6f8b46ec23..2e235aeb33 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUpdated.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUpdated.ts @@ -1,5 +1,5 @@ import { startAppListening } from '..'; -import { imageUpdated } from 'services/thunks/image'; +import { imageUpdated } from 'services/api/thunks/image'; import { log } from 'app/logging/useLogger'; const moduleLog = log.child({ namespace: 'image' }); 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 fc44d206c8..f55ed11c8f 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 { startAppListening } from '..'; -import { imageUploaded } from 'services/thunks/image'; +import { imageUploaded } from 'services/api/thunks/image'; import { addToast } from 'features/system/store/systemSlice'; import { log } from 'app/logging/useLogger'; import { imageUpserted } from 'features/gallery/store/imagesSlice'; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts index 2e365a20ac..c663c64361 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts @@ -1,6 +1,6 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { imageUrlsReceived } from 'services/thunks/image'; +import { imageUrlsReceived } from 'services/api/thunks/image'; import { imageUpdatedOne } from 'features/gallery/store/imagesSlice'; const moduleLog = log.child({ namespace: 'image' }); 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 9069e477ac..9aca82a32b 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 @@ -5,7 +5,7 @@ import { startAppListening } from '..'; import { initialImageSelected } from 'features/parameters/store/actions'; import { makeToast } from 'app/components/Toaster'; import { selectImagesById } from 'features/gallery/store/imagesSlice'; -import { isImageDTO } from 'services/types/guards'; +import { isImageDTO } from 'services/api/guards'; export const addInitialImageSelectedListener = () => { startAppListening({ diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts index cde7e22e3d..e357d38dc3 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts @@ -1,7 +1,7 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; import { serializeError } from 'serialize-error'; -import { receivedPageOfImages } from 'services/thunks/image'; +import { receivedPageOfImages } from 'services/api/thunks/image'; const moduleLog = log.child({ namespace: 'gallery' }); 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 6274ad4dc8..85e2627d88 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,6 +1,6 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { sessionCanceled } from 'services/thunks/session'; +import { sessionCanceled } from 'services/api/thunks/session'; import { serializeError } from 'serialize-error'; const moduleLog = log.child({ namespace: 'session' }); @@ -18,10 +18,10 @@ export const addSessionCanceledFulfilledListener = () => { startAppListening({ actionCreator: sessionCanceled.fulfilled, effect: (action, { getState, dispatch }) => { - const { sessionId } = action.meta.arg; + const { session_id } = action.meta.arg; moduleLog.debug( - { data: { sessionId } }, - `Session canceled (${sessionId})` + { data: { session_id } }, + `Session canceled (${session_id})` ); }, }); 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 fb8a64d2e3..c502b4e38c 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,6 +1,6 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { sessionCreated } from 'services/thunks/session'; +import { sessionCreated } from 'services/api/thunks/session'; import { serializeError } from 'serialize-error'; const moduleLog = log.child({ namespace: 'session' }); 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 272d1d9e1d..6aff246cbe 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,6 +1,6 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { sessionInvoked } from 'services/thunks/session'; +import { sessionInvoked } from 'services/api/thunks/session'; import { serializeError } from 'serialize-error'; const moduleLog = log.child({ namespace: 'session' }); @@ -18,10 +18,10 @@ export const addSessionInvokedFulfilledListener = () => { startAppListening({ actionCreator: sessionInvoked.fulfilled, effect: (action, { getState, dispatch }) => { - const { sessionId } = action.meta.arg; + const { session_id } = action.meta.arg; moduleLog.debug( - { data: { sessionId } }, - `Session invoked (${sessionId})` + { data: { session_id } }, + `Session invoked (${session_id})` ); }, }); 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 8d4262e7da..cc77403709 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,5 +1,5 @@ import { startAppListening } from '..'; -import { sessionInvoked } from 'services/thunks/session'; +import { sessionInvoked } from 'services/api/thunks/session'; import { log } from 'app/logging/useLogger'; import { sessionReadyToInvoke } from 'features/system/store/actions'; @@ -9,13 +9,13 @@ export const addSessionReadyToInvokeListener = () => { startAppListening({ actionCreator: sessionReadyToInvoke, effect: (action, { getState, dispatch }) => { - const { sessionId } = getState().system; - if (sessionId) { + const { sessionId: session_id } = getState().system; + if (session_id) { moduleLog.debug( - { sessionId }, - `Session ready to invoke (${sessionId})})` + { session_id }, + `Session ready to invoke (${session_id})})` ); - dispatch(sessionInvoked({ sessionId })); + 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 bf54e63836..976c1558d0 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,7 +1,7 @@ import { log } from 'app/logging/useLogger'; import { appSocketConnected, socketConnected } from 'services/events/actions'; -import { receivedPageOfImages } from 'services/thunks/image'; -import { receivedOpenAPISchema } from 'services/thunks/schema'; +import { receivedPageOfImages } from 'services/api/thunks/image'; +import { receivedOpenAPISchema } from 'services/api/thunks/schema'; import { startAppListening } from '../..'; const moduleLog = log.child({ namespace: 'socketio' }); @@ -22,7 +22,7 @@ export const addSocketConnectedEventListener = () => { dispatch( receivedPageOfImages({ categories: ['general'], - isIntermediate: false, + is_intermediate: false, }) ); } 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 c204f0bdfb..3686816d5c 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 @@ -5,11 +5,11 @@ import { appSocketInvocationComplete, socketInvocationComplete, } from 'services/events/actions'; -import { imageMetadataReceived } from 'services/thunks/image'; -import { sessionCanceled } from 'services/thunks/session'; -import { isImageOutput } from 'services/types/guards'; +import { imageMetadataReceived } from 'services/api/thunks/image'; +import { sessionCanceled } from 'services/api/thunks/session'; +import { isImageOutput } from 'services/api/guards'; import { progressImageSet } from 'features/system/store/systemSlice'; -import { api } from 'services/apiSlice'; +import { boardImagesApi } from 'services/api/endpoints/boardImages'; const moduleLog = log.child({ namespace: 'socketio' }); const nodeDenylist = ['dataURL_image']; @@ -19,18 +19,18 @@ export const addInvocationCompleteEventListener = () => { actionCreator: socketInvocationComplete, effect: async (action, { dispatch, getState, take }) => { moduleLog.debug( - action.payload, + { data: action.payload }, `Invocation complete (${action.payload.data.node.type})` ); - const sessionId = action.payload.data.graph_execution_state_id; + const session_id = action.payload.data.graph_execution_state_id; const { cancelType, isCancelScheduled, boardIdToAddTo } = getState().system; // Handle scheduled cancelation if (cancelType === 'scheduled' && isCancelScheduled) { - dispatch(sessionCanceled({ sessionId })); + dispatch(sessionCanceled({ session_id })); } const { data } = action.payload; @@ -43,7 +43,7 @@ export const addInvocationCompleteEventListener = () => { // Get its metadata dispatch( imageMetadataReceived({ - imageName: image_name, + image_name, }) ); @@ -61,7 +61,7 @@ export const addInvocationCompleteEventListener = () => { if (boardIdToAddTo && !imageDTO.is_intermediate) { dispatch( - api.endpoints.addImageToBoard.initiate({ + boardImagesApi.endpoints.addImageToBoard.initiate({ board_id: boardIdToAddTo, image_name, }) 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 3e211f73bb..bc2c1d1c27 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,7 +1,7 @@ import { stagingAreaImageSaved } from 'features/canvas/store/actions'; import { startAppListening } from '..'; import { log } from 'app/logging/useLogger'; -import { imageUpdated } from 'services/thunks/image'; +import { imageUpdated } from 'services/api/thunks/image'; import { imageUpserted } from 'features/gallery/store/imagesSlice'; import { addToast } from 'features/system/store/systemSlice'; @@ -11,14 +11,12 @@ export const addStagingAreaImageSavedListener = () => { startAppListening({ actionCreator: stagingAreaImageSaved, effect: async (action, { dispatch, getState, take }) => { - const { image_name } = action.payload; + const { imageName } = action.payload; dispatch( imageUpdated({ - imageName: image_name, - requestBody: { - is_intermediate: false, - }, + image_name: imageName, + is_intermediate: false, }) ); @@ -26,7 +24,7 @@ export const addStagingAreaImageSavedListener = () => { (action) => (imageUpdated.fulfilled.match(action) || imageUpdated.rejected.match(action)) && - action.meta.arg.imageName === image_name + action.meta.arg.image_name === imageName ); if (imageUpdated.rejected.match(imageUpdatedAction)) { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts index b9ddcea4c3..72313a75a3 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts @@ -5,9 +5,8 @@ import { generationSelector } from 'features/parameters/store/generationSelector import { canvasSelector } from 'features/canvas/store/canvasSelectors'; import { nodesSelecter } from 'features/nodes/store/nodesSlice'; import { controlNetSelector } from 'features/controlNet/store/controlNetSlice'; -import { ImageDTO } from 'services/api'; import { forEach, uniqBy } from 'lodash-es'; -import { imageUrlsReceived } from 'services/thunks/image'; +import { imageUrlsReceived } from 'services/api/thunks/image'; import { log } from 'app/logging/useLogger'; import { selectImagesEntities } from 'features/gallery/store/imagesSlice'; @@ -83,7 +82,7 @@ export const addUpdateImageUrlsOnConnectListener = () => { allUsedImages.forEach((image_name) => { dispatch( imageUrlsReceived({ - imageName: image_name, + image_name, }) ); }); 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 a26d872d50..1f9f773392 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,10 +1,10 @@ import { startAppListening } from '..'; -import { sessionCreated } from 'services/thunks/session'; +import { sessionCreated } from 'services/api/thunks/session'; import { buildCanvasGraph } from 'features/nodes/util/graphBuilders/buildCanvasGraph'; import { log } from 'app/logging/useLogger'; import { canvasGraphBuilt } from 'features/nodes/store/actions'; -import { imageUpdated, imageUploaded } from 'services/thunks/image'; -import { ImageDTO } from 'services/api'; +import { imageUpdated, imageUploaded } from 'services/api/thunks/image'; +import { ImageDTO } from 'services/api/types'; import { canvasSessionIdChanged, stagingAreaInitialized, @@ -75,13 +75,11 @@ export const addUserInvokedCanvasListener = () => { // upload the image, saving the request id const { requestId: initImageUploadedRequestId } = dispatch( imageUploaded({ - formData: { - file: new File([baseBlob], 'canvasInitImage.png', { - type: 'image/png', - }), - }, - imageCategory: 'general', - isIntermediate: true, + file: new File([baseBlob], 'canvasInitImage.png', { + type: 'image/png', + }), + image_category: 'general', + is_intermediate: true, }) ); @@ -100,13 +98,11 @@ export const addUserInvokedCanvasListener = () => { // upload the image, saving the request id const { requestId: maskImageUploadedRequestId } = dispatch( imageUploaded({ - formData: { - file: new File([maskBlob], 'canvasMaskImage.png', { - type: 'image/png', - }), - }, - imageCategory: 'mask', - isIntermediate: true, + file: new File([maskBlob], 'canvasMaskImage.png', { + type: 'image/png', + }), + image_category: 'mask', + is_intermediate: true, }) ); @@ -149,8 +145,8 @@ export const addUserInvokedCanvasListener = () => { if (['img2img', 'inpaint'].includes(generationMode) && canvasInitImage) { dispatch( imageUpdated({ - imageName: canvasInitImage.image_name, - requestBody: { session_id: sessionId }, + image_name: canvasInitImage.image_name, + session_id: sessionId, }) ); } @@ -159,8 +155,8 @@ export const addUserInvokedCanvasListener = () => { if (['inpaint'].includes(generationMode) && canvasMaskImage) { dispatch( imageUpdated({ - imageName: canvasMaskImage.image_name, - requestBody: { session_id: sessionId }, + image_name: canvasMaskImage.image_name, + session_id: sessionId, }) ); } 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 368d97a10f..202dd6f487 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,5 +1,5 @@ import { startAppListening } from '..'; -import { sessionCreated } from 'services/thunks/session'; +import { sessionCreated } from 'services/api/thunks/session'; import { log } from 'app/logging/useLogger'; import { imageToImageGraphBuilt } from 'features/nodes/store/actions'; import { userInvoked } from 'app/store/actions'; 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 6fda3db0d6..9fb0009b70 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,5 +1,5 @@ import { startAppListening } from '..'; -import { sessionCreated } from 'services/thunks/session'; +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'; 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 c76e0dfd4f..b024e94d9c 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,5 +1,5 @@ import { startAppListening } from '..'; -import { sessionCreated } from 'services/thunks/session'; +import { sessionCreated } from 'services/api/thunks/session'; import { log } from 'app/logging/useLogger'; import { textToImageGraphBuilt } from 'features/nodes/store/actions'; import { userInvoked } from 'app/store/actions'; diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 57a97168a3..8202c4fa76 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -31,7 +31,7 @@ import { stateSanitizer } from './middleware/devtools/stateSanitizer'; import { LOCALSTORAGE_PREFIX } from './constants'; import { serialize } from './enhancers/reduxRemember/serialize'; import { unserialize } from './enhancers/reduxRemember/unserialize'; -import { api } from 'services/apiSlice'; +import { api } from 'services/api'; const allReducers = { canvas: canvasReducer, diff --git a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx index e54b4a8872..bdf22c2df1 100644 --- a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx +++ b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx @@ -12,15 +12,14 @@ import IAIIconButton from 'common/components/IAIIconButton'; import { IAIImageLoadingFallback } from 'common/components/IAIImageFallback'; import ImageMetadataOverlay from 'common/components/ImageMetadataOverlay'; import { AnimatePresence } from 'framer-motion'; -import { ReactElement, SyntheticEvent, useCallback } from 'react'; +import { ReactElement, SyntheticEvent } from 'react'; import { memo, useRef } from 'react'; -import { FaImage, FaTimes, FaUndo, FaUpload } from 'react-icons/fa'; -import { ImageDTO } from 'services/api'; +import { FaImage, FaUndo, FaUpload } from 'react-icons/fa'; +import { ImageDTO } from 'services/api/types'; import { v4 as uuidv4 } from 'uuid'; import IAIDropOverlay from './IAIDropOverlay'; -import { PostUploadAction, imageUploaded } from 'services/thunks/image'; -import { useDropzone } from 'react-dropzone'; -import { useAppDispatch } from 'app/store/storeHooks'; +import { PostUploadAction } from 'services/api/thunks/image'; +import { useImageUploadButton } from 'common/hooks/useImageUploadButton'; type IAIDndImageProps = { image: ImageDTO | null | undefined; @@ -39,6 +38,7 @@ type IAIDndImageProps = { minSize?: number; postUploadAction?: PostUploadAction; imageSx?: ChakraProps['sx']; + fitContainer?: boolean; }; const IAIDndImage = (props: IAIDndImageProps) => { @@ -58,8 +58,9 @@ const IAIDndImage = (props: IAIDndImageProps) => { minSize = 24, postUploadAction, imageSx, + fitContainer = false, } = props; - const dispatch = useAppDispatch(); + const dndId = useRef(uuidv4()); const { @@ -87,31 +88,9 @@ const IAIDndImage = (props: IAIDndImageProps) => { disabled: isDragDisabled || !image, }); - const handleOnDropAccepted = useCallback( - (files: Array) => { - const file = files[0]; - if (!file) { - return; - } - - dispatch( - imageUploaded({ - formData: { file }, - imageCategory: 'user', - isIntermediate: false, - postUploadAction, - }) - ); - }, - [dispatch, postUploadAction] - ); - - const { getRootProps, getInputProps } = useDropzone({ - accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] }, - onDropAccepted: handleOnDropAccepted, - noDrag: true, - multiple: false, - disabled: isUploadDisabled, + const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({ + postUploadAction, + isDisabled: isUploadDisabled, }); const setNodeRef = useCombinedRefs(setDroppableRef, setDraggableRef); @@ -149,13 +128,13 @@ const IAIDndImage = (props: IAIDndImageProps) => { sx={{ w: 'full', h: 'full', + position: fitContainer ? 'absolute' : 'relative', alignItems: 'center', justifyContent: 'center', }} > { color: 'base.500', ...uploadButtonStyles, }} - {...getRootProps()} + {...getUploadButtonProps()} > - + { async (file: File) => { dispatch( imageUploaded({ - formData: { file }, - imageCategory: 'user', - isIntermediate: false, + file, + image_category: 'user', + is_intermediate: false, postUploadAction: { type: 'TOAST_UPLOADED' }, }) ); diff --git a/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx b/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx new file mode 100644 index 0000000000..0712daf742 --- /dev/null +++ b/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx @@ -0,0 +1,64 @@ +import { useAppDispatch } from 'app/store/storeHooks'; +import { useCallback } from 'react'; +import { useDropzone } from 'react-dropzone'; +import { PostUploadAction, imageUploaded } from 'services/api/thunks/image'; + +type UseImageUploadButtonArgs = { + postUploadAction?: PostUploadAction; + isDisabled?: boolean; +}; + +/** + * Provides image uploader functionality to any component. + * + * @example + * const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({ + * postUploadAction: { + * type: 'SET_CONTROLNET_IMAGE', + * controlNetId: '12345', + * }, + * isDisabled: getIsUploadDisabled(), + * }); + * + * // in the render function + *