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 0d0192143f..8a05c79a66 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 @@ -45,7 +45,7 @@ export const addCanvasMergedListener = () => { relativeTo: canvasBaseLayer.getParent(), }); - const imageUploadedRequest = dispatch( + const imageDTO = await dispatch( imagesApi.endpoints.uploadImage.initiate({ file: new File([blob], 'mergedCanvas.png', { type: 'image/png', @@ -57,17 +57,10 @@ export const addCanvasMergedListener = () => { toastOptions: { title: 'Canvas Merged' }, }, }) - ); - - const [{ payload }] = await take( - (uploadedImageAction) => - imagesApi.endpoints.uploadImage.matchFulfilled(uploadedImageAction) && - uploadedImageAction.meta.requestId === imageUploadedRequest.requestId - ); + ).unwrap(); // TODO: I can't figure out how to do the type narrowing in the `take()` so just brute forcing it here - const { image_name } = - payload as typeof imagesApi.endpoints.uploadImage.Types.ResultType; + const { image_name } = imageDTO; dispatch( setMergedCanvas({ 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 3b7b8e7b75..0e278240ca 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 @@ -34,6 +34,7 @@ export const addCanvasSavedToGalleryListener = () => { }), image_category: 'general', is_intermediate: false, + board_id: state.gallery.autoAddBoardId, postUploadAction: { type: 'TOAST', toastOptions: { title: 'Canvas Saved to Gallery' }, 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 1f24bdba2a..93519cca97 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 @@ -8,10 +8,7 @@ import { initialImageChanged } from 'features/parameters/store/generationSlice'; import { addToast } from 'features/system/store/systemSlice'; import { boardsApi } from 'services/api/endpoints/boards'; import { startAppListening } from '..'; -import { - SYSTEM_BOARDS, - imagesApi, -} from '../../../../../services/api/endpoints/images'; +import { imagesApi } from '../../../../../services/api/endpoints/images'; const moduleLog = log.child({ namespace: 'image' }); @@ -26,7 +23,7 @@ export const addImageUploadedFulfilledListener = () => { effect: (action, { dispatch, getState }) => { const imageDTO = action.payload; const state = getState(); - const { selectedBoardId } = state.gallery; + const { selectedBoardId, autoAddBoardId } = state.gallery; moduleLog.debug({ arg: '', imageDTO }, 'Image uploaded'); @@ -44,13 +41,13 @@ export const addImageUploadedFulfilledListener = () => { // default action - just upload and alert user if (postUploadAction?.type === 'TOAST') { const { toastOptions } = postUploadAction; - if (SYSTEM_BOARDS.includes(selectedBoardId)) { + if (!autoAddBoardId) { dispatch(addToast({ ...DEFAULT_UPLOADED_TOAST, ...toastOptions })); } else { // Add this image to the board dispatch( imagesApi.endpoints.addImageToBoard.initiate({ - board_id: selectedBoardId, + board_id: autoAddBoardId, imageDTO, }) ); @@ -59,10 +56,10 @@ export const addImageUploadedFulfilledListener = () => { const { data } = boardsApi.endpoints.listAllBoards.select()(state); // Fall back to just the board id if we can't find the board for some reason - const board = data?.find((b) => b.board_id === selectedBoardId); + const board = data?.find((b) => b.board_id === autoAddBoardId); const description = board ? `Added to board ${board.board_name}` - : `Added to board ${selectedBoardId}`; + : `Added to board ${autoAddBoardId}`; dispatch( addToast({ 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 df67f286d6..83c1a9f716 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 @@ -56,9 +56,16 @@ export const addInvocationCompleteEventListener = () => { } if (!imageDTO.is_intermediate) { - const { autoAddBoardId } = gallery; + /** + * Cache updates for when an image result is received + * - *add* to getImageDTO + * - IF `autoAddBoardId` is set: + * - THEN add it to the board_id/images + * - ELSE (`autoAddBoardId` is not set): + * - THEN add it to the no_board/images + */ - // add image to the board if auto-add is enabled + const { autoAddBoardId } = gallery; if (autoAddBoardId) { dispatch( imagesApi.endpoints.addImageToBoard.initiate({ @@ -67,8 +74,6 @@ export const addInvocationCompleteEventListener = () => { }) ); } else { - // add to no board board - // update the cache for 'No Board' dispatch( imagesApi.util.updateQueryData( 'listImages', @@ -77,8 +82,10 @@ export const addInvocationCompleteEventListener = () => { categories: IMAGE_CATEGORIES, }, (draft) => { - imagesAdapter.addOne(draft, imageDTO); - draft.total = draft.total + 1; + const oldTotal = draft.total; + const newState = imagesAdapter.addOne(draft, imageDTO); + const delta = newState.total - oldTotal; + draft.total = draft.total + delta; } ) ); 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 903d2472b2..1d175e6e90 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 @@ -12,25 +12,35 @@ export const addStagingAreaImageSavedListener = () => { effect: async (action, { dispatch, getState, take }) => { const { imageDTO } = action.payload; - dispatch( - imagesApi.endpoints.updateImage.initiate({ - imageDTO, - changes: { is_intermediate: false }, - }) - ) - .unwrap() - .then((image) => { - dispatch(addToast({ title: 'Image Saved', status: 'success' })); - }) - .catch((error) => { - dispatch( - addToast({ - title: 'Image Saving Failed', - description: error.message, - status: 'error', + try { + const newImageDTO = await dispatch( + imagesApi.endpoints.changeImageIsIntermediate.initiate({ + imageDTO, + is_intermediate: false, + }) + ).unwrap(); + + // we may need to add it to the autoadd board + const { autoAddBoardId } = getState().gallery; + + if (autoAddBoardId) { + await dispatch( + imagesApi.endpoints.addImageToBoard.initiate({ + imageDTO: newImageDTO, + board_id: autoAddBoardId, }) ); - }); + } + dispatch(addToast({ title: 'Image Saved', status: 'success' })); + } catch (error) { + dispatch( + addToast({ + title: 'Image Saving Failed', + description: (error as Error)?.message, + status: 'error', + }) + ); + } }, }); }; 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 afddaf8bea..6cfe2a58fb 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 @@ -73,7 +73,7 @@ export const addUserInvokedCanvasListener = () => { // For img2img and inpaint/outpaint, we need to upload the init images if (['img2img', 'inpaint', 'outpaint'].includes(generationMode)) { // upload the image, saving the request id - const { requestId: initImageUploadedRequestId } = dispatch( + canvasInitImage = await dispatch( imagesApi.endpoints.uploadImage.initiate({ file: new File([baseBlob], 'canvasInitImage.png', { type: 'image/png', @@ -81,23 +81,13 @@ export const addUserInvokedCanvasListener = () => { image_category: 'general', is_intermediate: true, }) - ); - - // Wait for the image to be uploaded, matching by request id - const [{ payload }] = await take( - // TODO: figure out how to narrow this action's type - (action) => - imagesApi.endpoints.uploadImage.matchFulfilled(action) && - action.meta.requestId === initImageUploadedRequestId - ); - - canvasInitImage = payload as ImageDTO; + ).unwrap(); } // For inpaint/outpaint, we also need to upload the mask layer if (['inpaint', 'outpaint'].includes(generationMode)) { // upload the image, saving the request id - const { requestId: maskImageUploadedRequestId } = dispatch( + canvasMaskImage = await dispatch( imagesApi.endpoints.uploadImage.initiate({ file: new File([maskBlob], 'canvasMaskImage.png', { type: 'image/png', @@ -105,17 +95,7 @@ export const addUserInvokedCanvasListener = () => { image_category: 'mask', is_intermediate: true, }) - ); - - // Wait for the image to be uploaded, matching by request id - const [{ payload }] = await take( - // TODO: figure out how to narrow this action's type - (action) => - imagesApi.endpoints.uploadImage.matchFulfilled(action) && - action.meta.requestId === maskImageUploadedRequestId - ); - - canvasMaskImage = payload as ImageDTO; + ).unwrap(); } const graph = buildCanvasGraph( @@ -141,14 +121,14 @@ export const addUserInvokedCanvasListener = () => { sessionCreated.fulfilled.match(action) && action.meta.requestId === sessionCreatedRequestId ); - const sessionId = sessionCreatedAction.payload.id; + const session_id = sessionCreatedAction.payload.id; // Associate the init image with the session, now that we have the session ID if (['img2img', 'inpaint'].includes(generationMode) && canvasInitImage) { dispatch( - imagesApi.endpoints.updateImage.initiate({ + imagesApi.endpoints.changeImageSessionId.initiate({ imageDTO: canvasInitImage, - changes: { session_id: sessionId }, + session_id, }) ); } @@ -156,9 +136,9 @@ export const addUserInvokedCanvasListener = () => { // Associate the mask image with the session, now that we have the session ID if (['inpaint'].includes(generationMode) && canvasMaskImage) { dispatch( - imagesApi.endpoints.updateImage.initiate({ + imagesApi.endpoints.changeImageSessionId.initiate({ imageDTO: canvasMaskImage, - changes: { session_id: sessionId }, + session_id, }) ); } @@ -167,7 +147,7 @@ export const addUserInvokedCanvasListener = () => { if (!state.canvas.layerState.stagingArea.boundingBox) { dispatch( stagingAreaInitialized({ - sessionId, + sessionId: session_id, boundingBox: { ...state.canvas.boundingBoxCoordinates, ...state.canvas.boundingBoxDimensions, @@ -177,7 +157,7 @@ export const addUserInvokedCanvasListener = () => { } // Flag the session with the canvas session ID - dispatch(canvasSessionIdChanged(sessionId)); + dispatch(canvasSessionIdChanged(session_id)); // We are ready to invoke the session! dispatch(sessionReadyToInvoke()); diff --git a/invokeai/frontend/web/src/common/components/ImageUploader.tsx b/invokeai/frontend/web/src/common/components/ImageUploader.tsx index dbdaf26c5b..de347b8381 100644 --- a/invokeai/frontend/web/src/common/components/ImageUploader.tsx +++ b/invokeai/frontend/web/src/common/components/ImageUploader.tsx @@ -19,10 +19,11 @@ import { useUploadImageMutation } from 'services/api/endpoints/images'; import { PostUploadAction } from 'services/api/types'; import ImageUploadOverlay from './ImageUploadOverlay'; import { AnimatePresence, motion } from 'framer-motion'; +import { stateSelector } from 'app/store/store'; const selector = createSelector( - [activeTabNameSelector], - (activeTabName) => { + [stateSelector, activeTabNameSelector], + ({ gallery }, activeTabName) => { let postUploadAction: PostUploadAction = { type: 'TOAST' }; if (activeTabName === 'unifiedCanvas') { @@ -33,7 +34,10 @@ const selector = createSelector( postUploadAction = { type: 'SET_INITIAL_IMAGE' }; } + const { autoAddBoardId } = gallery; + return { + autoAddBoardId, postUploadAction, }; }, @@ -46,7 +50,7 @@ type ImageUploaderProps = { const ImageUploader = (props: ImageUploaderProps) => { const { children } = props; - const { postUploadAction } = useAppSelector(selector); + const { autoAddBoardId, postUploadAction } = useAppSelector(selector); const isBusy = useAppSelector(selectIsBusy); const toaster = useAppToaster(); const { t } = useTranslation(); @@ -74,9 +78,10 @@ const ImageUploader = (props: ImageUploaderProps) => { image_category: 'user', is_intermediate: false, postUploadAction, + board_id: autoAddBoardId, }); }, - [postUploadAction, uploadImage] + [autoAddBoardId, postUploadAction, uploadImage] ); const onDrop = useCallback( diff --git a/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx b/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx index fad6deb350..c04c0182cd 100644 --- a/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx +++ b/invokeai/frontend/web/src/common/hooks/useImageUploadButton.tsx @@ -1,3 +1,4 @@ +import { useAppSelector } from 'app/store/storeHooks'; import { useCallback } from 'react'; import { useDropzone } from 'react-dropzone'; import { useUploadImageMutation } from 'services/api/endpoints/images'; @@ -31,6 +32,9 @@ export const useImageUploadButton = ({ postUploadAction, isDisabled, }: UseImageUploadButtonArgs) => { + const autoAddBoardId = useAppSelector( + (state) => state.gallery.autoAddBoardId + ); const [uploadImage] = useUploadImageMutation(); const onDropAccepted = useCallback( (files: File[]) => { @@ -45,9 +49,10 @@ export const useImageUploadButton = ({ image_category: 'user', is_intermediate: false, postUploadAction: postUploadAction ?? { type: 'TOAST' }, + board_id: autoAddBoardId, }); }, - [postUploadAction, uploadImage] + [autoAddBoardId, postUploadAction, uploadImage] ); const { diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx index e9052a20c9..53f0293afa 100644 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/Boards/AutoAddIcon.tsx @@ -12,7 +12,7 @@ const AutoAddIcon = () => { > auto diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AllAssetsBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AllAssetsBoard.tsx deleted file mode 100644 index 76f6238cd0..0000000000 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AllAssetsBoard.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { - ASSETS_CATEGORIES, - INITIAL_IMAGE_LIMIT, - boardIdSelected, -} from 'features/gallery/store/gallerySlice'; -import { FaFileImage } from 'react-icons/fa'; -import { useDispatch } from 'react-redux'; -import { - ListImagesArgs, - useListImagesQuery, -} from 'services/api/endpoints/images'; -import GenericBoard from './GenericBoard'; - -const baseQueryArg: ListImagesArgs = { - categories: ASSETS_CATEGORIES, - offset: 0, - limit: INITIAL_IMAGE_LIMIT, - is_intermediate: false, -}; - -const AllAssetsBoard = ({ isSelected }: { isSelected: boolean }) => { - const dispatch = useDispatch(); - - const handleClick = () => { - dispatch(boardIdSelected('assets')); - }; - - const { total } = useListImagesQuery(baseQueryArg, { - selectFromResult: ({ data }) => ({ total: data?.total ?? 0 }), - }); - - // TODO: Do we support making 'images' 'assets? if yes, we need to handle this - // const droppableData: MoveBoardDropData = { - // id: 'all-images-board', - // actionType: 'MOVE_BOARD', - // context: { boardId: 'assets' }, - // }; - - return ( - - ); -}; - -export default AllAssetsBoard; diff --git a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AllImagesBoard.tsx b/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AllImagesBoard.tsx deleted file mode 100644 index 084bc1653b..0000000000 --- a/invokeai/frontend/web/src/features/gallery/components/Boards/BoardsList/AllImagesBoard.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { - IMAGE_CATEGORIES, - INITIAL_IMAGE_LIMIT, - boardIdSelected, -} from 'features/gallery/store/gallerySlice'; -import { FaImages } from 'react-icons/fa'; -import { useDispatch } from 'react-redux'; -import { - ListImagesArgs, - useListImagesQuery, -} from 'services/api/endpoints/images'; -import GenericBoard from './GenericBoard'; - -const baseQueryArg: ListImagesArgs = { - categories: IMAGE_CATEGORIES, - offset: 0, - limit: INITIAL_IMAGE_LIMIT, - is_intermediate: false, -}; - -const AllImagesBoard = ({ isSelected }: { isSelected: boolean }) => { - const dispatch = useDispatch(); - - const handleClick = () => { - dispatch(boardIdSelected('images')); - }; - - const { total } = useListImagesQuery(baseQueryArg, { - selectFromResult: ({ data }) => ({ total: data?.total ?? 0 }), - }); - - // TODO: Do we support making 'images' 'assets? if yes, we need to handle this - // const droppableData: MoveBoardDropData = { - // id: 'all-images-board', - // actionType: 'MOVE_BOARD', - // context: { boardId: 'images' }, - // }; - - return ( - - ); -}; - -export default AllImagesBoard; 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 0043df5646..841ee5120d 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 @@ -72,9 +72,9 @@ const NoBoardBoard = memo(({ isSelected }: Props) => { alignItems: 'center', borderRadius: 'base', cursor: 'pointer', - bg: 'base.300', + bg: 'base.200', _dark: { - bg: 'base.900', + bg: 'base.800', }, }} > diff --git a/invokeai/frontend/web/src/features/gallery/store/util.ts b/invokeai/frontend/web/src/features/gallery/store/util.ts index dfe812822f..3df5b2af31 100644 --- a/invokeai/frontend/web/src/features/gallery/store/util.ts +++ b/invokeai/frontend/web/src/features/gallery/store/util.ts @@ -1,12 +1,6 @@ -import { ListImagesArgs, SYSTEM_BOARDS } from 'services/api/endpoints/images'; -import { - ASSETS_CATEGORIES, - BoardId, - GalleryView, - IMAGE_CATEGORIES, -} from './gallerySlice'; -import { ImageCategory, ImageDTO } from 'services/api/types'; 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 diff --git a/invokeai/frontend/web/src/services/api/endpoints/images.ts b/invokeai/frontend/web/src/services/api/endpoints/images.ts index d1bf8e3977..c905ec5784 100644 --- a/invokeai/frontend/web/src/services/api/endpoints/images.ts +++ b/invokeai/frontend/web/src/services/api/endpoints/images.ts @@ -50,8 +50,6 @@ export const imagesSelectors = imagesAdapter.getSelectors(); export const getListImagesUrl = (queryArgs: ListImagesArgs) => `images/?${queryString.stringify(queryArgs, { arrayFormat: 'none' })}`; -export const SYSTEM_BOARDS = ['images', 'assets', 'no_board', 'batch']; - export const imagesApi = api.injectEndpoints({ endpoints: (build) => ({ /** @@ -315,6 +313,7 @@ export const imagesApi = api.injectEndpoints({ ); } else { // ELSE (it is being changed to a non-intermediate): + console.log(imageDTO); const queryArgs = { board_id: imageDTO.board_id ?? 'none', categories, @@ -421,9 +420,16 @@ export const imagesApi = api.injectEndpoints({ is_intermediate: boolean; postUploadAction?: PostUploadAction; session_id?: string; + board_id?: string; } >({ - query: ({ file, image_category, is_intermediate, session_id }) => { + query: ({ + file, + image_category, + is_intermediate, + session_id, + board_id, + }) => { const formData = new FormData(); formData.append('file', file); return { @@ -434,11 +440,19 @@ export const imagesApi = api.injectEndpoints({ image_category, is_intermediate, session_id, + board_id, }, }; }, async onQueryStarted( - { file, image_category, is_intermediate, postUploadAction }, + { + file, + image_category, + is_intermediate, + postUploadAction, + session_id, + board_id, + }, { dispatch, queryFulfilled } ) { try { @@ -467,11 +481,16 @@ export const imagesApi = api.injectEndpoints({ ) ); + const categories = getCategories(imageDTO); + // *add* to no_board/assets dispatch( imagesApi.util.updateQueryData( 'listImages', - { board_id: 'none', categories: ASSETS_CATEGORIES }, + { + board_id: imageDTO.board_id ?? 'none', + categories, + }, (draft) => { const oldTotal = draft.total; const newState = imagesAdapter.addOne(draft, imageDTO); @@ -518,6 +537,8 @@ export const imagesApi = api.injectEndpoints({ /** * Cache changes for `addImageToBoard`: * - *update* getImageDTO + * - IF it is intermediate: + * - BAIL OUT ON FURTHER CHANGES * - IF it has an old board_id: * - THEN *remove* from old board_id/[images|assets] * - ELSE *remove* from no_board/[images|assets] @@ -542,65 +563,67 @@ export const imagesApi = api.injectEndpoints({ ) ); - // *remove* from [no_board|board_id]/[images|assets] - patches.push( - dispatch( - imagesApi.util.updateQueryData( - 'listImages', - { - board_id: imageDTO.board_id ?? 'none', - categories, - }, - (draft) => { - const oldTotal = draft.total; - const newState = imagesAdapter.removeOne( - draft, - imageDTO.image_name - ); - const delta = newState.total - oldTotal; - draft.total = draft.total + delta; - } - ) - ) - ); - - // $cache = board_id/[images|assets] - const queryArgs = { board_id: board_id ?? 'none', categories }; - const currentCache = imagesApi.endpoints.listImages.select(queryArgs)( - getState() - ); - - // IF it eligible for insertion into existing $cache - // "eligible" means either: - // - The cache is fully populated, with all images in the db cached - // OR - // - The image's `created_at` is within the range of the cached images - - const isCacheFullyPopulated = - currentCache.data && - currentCache.data.ids.length >= currentCache.data.total; - - const isInDateRange = getIsImageInDateRange( - currentCache.data, - imageDTO - ); - - if (isCacheFullyPopulated || isInDateRange) { - // THEN *add* to $cache + if (!imageDTO.is_intermediate) { + // *remove* from [no_board|board_id]/[images|assets] patches.push( dispatch( imagesApi.util.updateQueryData( 'listImages', - queryArgs, + { + board_id: imageDTO.board_id ?? 'none', + categories, + }, (draft) => { const oldTotal = draft.total; - const newState = imagesAdapter.addOne(draft, imageDTO); + const newState = imagesAdapter.removeOne( + draft, + imageDTO.image_name + ); const delta = newState.total - oldTotal; draft.total = draft.total + delta; } ) ) ); + + // $cache = board_id/[images|assets] + const queryArgs = { board_id: board_id ?? 'none', categories }; + const currentCache = imagesApi.endpoints.listImages.select(queryArgs)( + getState() + ); + + // IF it eligible for insertion into existing $cache + // "eligible" means either: + // - The cache is fully populated, with all images in the db cached + // OR + // - The image's `created_at` is within the range of the cached images + + const isCacheFullyPopulated = + currentCache.data && + currentCache.data.ids.length >= currentCache.data.total; + + const isInDateRange = getIsImageInDateRange( + currentCache.data, + imageDTO + ); + + if (isCacheFullyPopulated || isInDateRange) { + // THEN *add* to $cache + patches.push( + dispatch( + imagesApi.util.updateQueryData( + 'listImages', + queryArgs, + (draft) => { + const oldTotal = draft.total; + const newState = imagesAdapter.addOne(draft, imageDTO); + const delta = newState.total - oldTotal; + draft.total = draft.total + delta; + } + ) + ) + ); + } } try { @@ -733,7 +756,6 @@ export const { useGetImageDTOQuery, useGetImageMetadataQuery, useDeleteImageMutation, - // useUpdateImageMutation, useGetBoardImagesTotalQuery, useGetBoardAssetsTotalQuery, useUploadImageMutation, diff --git a/invokeai/frontend/web/src/services/api/schema.d.ts b/invokeai/frontend/web/src/services/api/schema.d.ts index 100eda6432..59f2416ceb 100644 --- a/invokeai/frontend/web/src/services/api/schema.d.ts +++ b/invokeai/frontend/web/src/services/api/schema.d.ts @@ -1305,7 +1305,7 @@ export type components = { * @description The nodes in this graph */ nodes?: { - [key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["ParamStringInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined; + [key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["ParamStringInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined; }; /** * Edges @@ -1348,7 +1348,7 @@ export type components = { * @description The results of node executions */ results: { - [key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["MetadataAccumulatorOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined; + [key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["MetadataAccumulatorOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined; }; /** * Errors @@ -5483,7 +5483,7 @@ export type operations = { }; requestBody: { content: { - "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["ParamStringInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; + "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["ParamStringInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; }; }; responses: { @@ -5520,7 +5520,7 @@ export type operations = { }; requestBody: { content: { - "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["ParamStringInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; + "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["MetadataAccumulatorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["SDXLRawPromptInvocation"] | components["schemas"]["SDXLRefinerRawPromptInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["SDXLTextToLatentsInvocation"] | components["schemas"]["SDXLLatentsToLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["ParamStringInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; }; }; responses: { @@ -6046,6 +6046,8 @@ export type operations = { image_category: components["schemas"]["ImageCategory"]; /** @description Whether this is an intermediate image */ is_intermediate: boolean; + /** @description The board to add this image to, if any */ + board_id?: string; /** @description The session ID associated with this upload, if any */ session_id?: string; };