merge with main

This commit is contained in:
Lincoln Stein 2023-07-08 10:11:25 -04:00
commit bd9786564c
45 changed files with 782 additions and 1637 deletions

View File

@ -0,0 +1,18 @@
from fastapi.routing import APIRouter
from pydantic import BaseModel
from invokeai.version import __version__
app_router = APIRouter(prefix="/v1/app", tags=['app'])
class AppVersion(BaseModel):
"""App Version Response"""
version: str
@app_router.get('/version', operation_id="app_version",
status_code=200,
response_model=AppVersion)
async def get_version() -> AppVersion:
return AppVersion(version=__version__)

View File

@ -31,7 +31,7 @@ if app_config.version:
import invokeai.frontend.web as web_dir import invokeai.frontend.web as web_dir
from .api.dependencies import ApiDependencies from .api.dependencies import ApiDependencies
from .api.routers import sessions, models, images, boards, board_images from .api.routers import sessions, models, images, boards, board_images, app_info
from .api.sockets import SocketIO from .api.sockets import SocketIO
from .invocations.baseinvocation import BaseInvocation from .invocations.baseinvocation import BaseInvocation
@ -94,6 +94,8 @@ app.include_router(boards.boards_router, prefix="/api")
app.include_router(board_images.board_images_router, prefix="/api") app.include_router(board_images.board_images_router, prefix="/api")
app.include_router(app_info.app_router, prefix='/api')
# Build a custom OpenAPI to include all outputs # Build a custom OpenAPI to include all outputs
# TODO: can outputs be included on metadata of invocation schemas somehow? # TODO: can outputs be included on metadata of invocation schemas somehow?
def custom_openapi(): def custom_openapi():

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@
margin: 0; margin: 0;
} }
</style> </style>
<script type="module" crossorigin src="./assets/index-43f18910.js"></script> <script type="module" crossorigin src="./assets/index-12a7dbbd.js"></script>
</head> </head>
<body dir="ltr"> <body dir="ltr">

View File

@ -1,5 +1,6 @@
import { Flex, Grid, Portal } from '@chakra-ui/react'; import { Flex, Grid, Portal } from '@chakra-ui/react';
import { useLogger } from 'app/logging/useLogger'; import { useLogger } from 'app/logging/useLogger';
import { appStarted } from 'app/store/middleware/listenerMiddleware/listeners/appStarted';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { PartialAppConfig } from 'app/types/invokeai'; import { PartialAppConfig } from 'app/types/invokeai';
import ImageUploader from 'common/components/ImageUploader'; import ImageUploader from 'common/components/ImageUploader';
@ -46,6 +47,10 @@ const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => {
dispatch(configChanged(config)); dispatch(configChanged(config));
}, [dispatch, config, log]); }, [dispatch, config, log]);
useEffect(() => {
dispatch(appStarted());
}, [dispatch]);
return ( return (
<> <>
<Grid w="100vw" h="100vh" position="relative" overflow="hidden"> <Grid w="100vw" h="100vh" position="relative" overflow="hidden">

View File

@ -55,6 +55,7 @@ const DragPreview = (props: OverlayDragImageProps) => {
} }
if (props.dragData.payloadType === 'IMAGE_DTO') { if (props.dragData.payloadType === 'IMAGE_DTO') {
const { thumbnail_url, width, height } = props.dragData.payload.imageDTO;
return ( return (
<Box <Box
sx={{ sx={{
@ -72,7 +73,10 @@ const DragPreview = (props: OverlayDragImageProps) => {
sx={{ sx={{
...STYLES, ...STYLES,
}} }}
src={props.dragData.payload.imageDTO.thumbnail_url} objectFit="contain"
src={thumbnail_url}
width={width}
height={height}
/> />
</Box> </Box>
); );

View File

@ -9,4 +9,5 @@ export const actionsDenylist = [
'canvas/addPointToCurrentLine', 'canvas/addPointToCurrentLine',
'socket/socketGeneratorProgress', 'socket/socketGeneratorProgress',
'socket/appSocketGeneratorProgress', 'socket/appSocketGeneratorProgress',
'hotkeys/shiftKeyPressed',
]; ];

View File

@ -1,49 +1,67 @@
import type { TypedAddListener, TypedStartListening } from '@reduxjs/toolkit';
import { import {
createListenerMiddleware,
addListener,
ListenerEffect,
AnyAction, AnyAction,
ListenerEffect,
addListener,
createListenerMiddleware,
} from '@reduxjs/toolkit'; } from '@reduxjs/toolkit';
import type { TypedStartListening, TypedAddListener } from '@reduxjs/toolkit';
import type { RootState, AppDispatch } from '../../store'; import type { AppDispatch, RootState } from '../../store';
import { addInitialImageSelectedListener } from './listeners/initialImageSelected'; import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener';
import { addAppStartedListener } from './listeners/appStarted';
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
import { addRequestedBoardImageDeletionListener } from './listeners/boardImagesDeleted';
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
import { addCanvasMergedListener } from './listeners/canvasMerged';
import { addCanvasSavedToGalleryListener } from './listeners/canvasSavedToGallery';
import { addControlNetAutoProcessListener } from './listeners/controlNetAutoProcess';
import { addControlNetImageProcessedListener } from './listeners/controlNetImageProcessed';
import { import {
addImageUploadedFulfilledListener, addImageAddedToBoardFulfilledListener,
addImageUploadedRejectedListener, addImageAddedToBoardRejectedListener,
} from './listeners/imageUploaded'; } from './listeners/imageAddedToBoard';
import { import {
addImageDeletedFulfilledListener, addImageDeletedFulfilledListener,
addImageDeletedPendingListener, addImageDeletedPendingListener,
addImageDeletedRejectedListener, addImageDeletedRejectedListener,
addRequestedImageDeletionListener, addRequestedImageDeletionListener,
} from './listeners/imageDeleted'; } from './listeners/imageDeleted';
import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas'; import { addImageDroppedListener } from './listeners/imageDropped';
import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage';
import { addCanvasSavedToGalleryListener } from './listeners/canvasSavedToGallery';
import { addCanvasDownloadedAsImageListener } from './listeners/canvasDownloadedAsImage';
import { addCanvasCopiedToClipboardListener } from './listeners/canvasCopiedToClipboard';
import { addCanvasMergedListener } from './listeners/canvasMerged';
import { addGeneratorProgressEventListener as addGeneratorProgressListener } from './listeners/socketio/socketGeneratorProgress';
import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCompleteListener } from './listeners/socketio/socketGraphExecutionStateComplete';
import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
import { addSocketConnectedEventListener as addSocketConnectedListener } from './listeners/socketio/socketConnected';
import { addSocketDisconnectedEventListener as addSocketDisconnectedListener } from './listeners/socketio/socketDisconnected';
import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
import { addSessionReadyToInvokeListener } from './listeners/sessionReadyToInvoke';
import { import {
addImageMetadataReceivedFulfilledListener, addImageMetadataReceivedFulfilledListener,
addImageMetadataReceivedRejectedListener, addImageMetadataReceivedRejectedListener,
} from './listeners/imageMetadataReceived'; } from './listeners/imageMetadataReceived';
import {
addImageRemovedFromBoardFulfilledListener,
addImageRemovedFromBoardRejectedListener,
} from './listeners/imageRemovedFromBoard';
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
import {
addImageUpdatedFulfilledListener,
addImageUpdatedRejectedListener,
} from './listeners/imageUpdated';
import {
addImageUploadedFulfilledListener,
addImageUploadedRejectedListener,
} from './listeners/imageUploaded';
import { import {
addImageUrlsReceivedFulfilledListener, addImageUrlsReceivedFulfilledListener,
addImageUrlsReceivedRejectedListener, addImageUrlsReceivedRejectedListener,
} from './listeners/imageUrlsReceived'; } from './listeners/imageUrlsReceived';
import { addInitialImageSelectedListener } from './listeners/initialImageSelected';
import { addModelSelectedListener } from './listeners/modelSelected';
import { addReceivedOpenAPISchemaListener } from './listeners/receivedOpenAPISchema';
import {
addReceivedPageOfImagesFulfilledListener,
addReceivedPageOfImagesRejectedListener,
} from './listeners/receivedPageOfImages';
import { addSelectionAddedToBatchListener } from './listeners/selectionAddedToBatch';
import {
addSessionCanceledFulfilledListener,
addSessionCanceledPendingListener,
addSessionCanceledRejectedListener,
} from './listeners/sessionCanceled';
import { import {
addSessionCreatedFulfilledListener, addSessionCreatedFulfilledListener,
addSessionCreatedPendingListener, addSessionCreatedPendingListener,
@ -54,39 +72,21 @@ import {
addSessionInvokedPendingListener, addSessionInvokedPendingListener,
addSessionInvokedRejectedListener, addSessionInvokedRejectedListener,
} from './listeners/sessionInvoked'; } from './listeners/sessionInvoked';
import { import { addSessionReadyToInvokeListener } from './listeners/sessionReadyToInvoke';
addSessionCanceledFulfilledListener, import { addSocketConnectedEventListener as addSocketConnectedListener } from './listeners/socketio/socketConnected';
addSessionCanceledPendingListener, import { addSocketDisconnectedEventListener as addSocketDisconnectedListener } from './listeners/socketio/socketDisconnected';
addSessionCanceledRejectedListener, import { addGeneratorProgressEventListener as addGeneratorProgressListener } from './listeners/socketio/socketGeneratorProgress';
} from './listeners/sessionCanceled'; import { addGraphExecutionStateCompleteEventListener as addGraphExecutionStateCompleteListener } from './listeners/socketio/socketGraphExecutionStateComplete';
import { import { addInvocationCompleteEventListener as addInvocationCompleteListener } from './listeners/socketio/socketInvocationComplete';
addImageUpdatedFulfilledListener, import { addInvocationErrorEventListener as addInvocationErrorListener } from './listeners/socketio/socketInvocationError';
addImageUpdatedRejectedListener, import { addInvocationStartedEventListener as addInvocationStartedListener } from './listeners/socketio/socketInvocationStarted';
} from './listeners/imageUpdated'; import { addSocketSubscribedEventListener as addSocketSubscribedListener } from './listeners/socketio/socketSubscribed';
import { import { addSocketUnsubscribedEventListener as addSocketUnsubscribedListener } from './listeners/socketio/socketUnsubscribed';
addReceivedPageOfImagesFulfilledListener,
addReceivedPageOfImagesRejectedListener,
} from './listeners/receivedPageOfImages';
import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved'; import { addStagingAreaImageSavedListener } from './listeners/stagingAreaImageSaved';
import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingAreaImageListener'; import { addUserInvokedCanvasListener } from './listeners/userInvokedCanvas';
import { addImageCategoriesChangedListener } from './listeners/imageCategoriesChanged'; import { addUserInvokedImageToImageListener } from './listeners/userInvokedImageToImage';
import { addControlNetImageProcessedListener } from './listeners/controlNetImageProcessed'; import { addUserInvokedNodesListener } from './listeners/userInvokedNodes';
import { addControlNetAutoProcessListener } from './listeners/controlNetAutoProcess'; import { addUserInvokedTextToImageListener } from './listeners/userInvokedTextToImage';
import {
addImageAddedToBoardFulfilledListener,
addImageAddedToBoardRejectedListener,
} from './listeners/imageAddedToBoard';
import { addBoardIdSelectedListener } from './listeners/boardIdSelected';
import {
addImageRemovedFromBoardFulfilledListener,
addImageRemovedFromBoardRejectedListener,
} from './listeners/imageRemovedFromBoard';
import { addReceivedOpenAPISchemaListener } from './listeners/receivedOpenAPISchema';
import { addRequestedBoardImageDeletionListener } from './listeners/boardImagesDeleted';
import { addSelectionAddedToBatchListener } from './listeners/selectionAddedToBatch';
import { addImageDroppedListener } from './listeners/imageDropped';
import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected';
import { addModelSelectedListener } from './listeners/modelSelected';
export const listenerMiddleware = createListenerMiddleware(); export const listenerMiddleware = createListenerMiddleware();
@ -196,9 +196,6 @@ addSessionCanceledRejectedListener();
addReceivedPageOfImagesFulfilledListener(); addReceivedPageOfImagesFulfilledListener();
addReceivedPageOfImagesRejectedListener(); addReceivedPageOfImagesRejectedListener();
// Gallery
addImageCategoriesChangedListener();
// ControlNet // ControlNet
addControlNetImageProcessedListener(); addControlNetImageProcessedListener();
addControlNetAutoProcessListener(); addControlNetAutoProcessListener();
@ -224,3 +221,6 @@ addImageDroppedListener();
// Models // Models
addModelSelectedListener(); addModelSelectedListener();
// app startup
addAppStartedListener();

View File

@ -0,0 +1,43 @@
import { createAction } from '@reduxjs/toolkit';
import {
INITIAL_IMAGE_LIMIT,
isLoadingChanged,
} from 'features/gallery/store/gallerySlice';
import { receivedPageOfImages } from 'services/api/thunks/image';
import { startAppListening } from '..';
export const appStarted = createAction('app/appStarted');
export const addAppStartedListener = () => {
startAppListening({
actionCreator: appStarted,
effect: async (
action,
{ getState, dispatch, unsubscribe, cancelActiveListeners }
) => {
cancelActiveListeners();
unsubscribe();
// fill up the gallery tab with images
await dispatch(
receivedPageOfImages({
categories: ['general'],
is_intermediate: false,
offset: 0,
limit: INITIAL_IMAGE_LIMIT,
})
);
// fill up the assets tab with images
await dispatch(
receivedPageOfImages({
categories: ['control', 'mask', 'user', 'other'],
is_intermediate: false,
offset: 0,
limit: INITIAL_IMAGE_LIMIT,
})
);
dispatch(isLoadingChanged(false));
},
});
};

View File

@ -1,29 +0,0 @@
import { log } from 'app/logging/useLogger';
import { startAppListening } from '..';
import { receivedPageOfImages } from 'services/api/thunks/image';
import {
imageCategoriesChanged,
selectFilteredImages,
} from 'features/gallery/store/gallerySlice';
const moduleLog = log.child({ namespace: 'gallery' });
export const addImageCategoriesChangedListener = () => {
startAppListening({
actionCreator: imageCategoriesChanged,
effect: (action, { getState, dispatch }) => {
const state = getState();
const filteredImagesCount = selectFilteredImages(state).length;
if (!filteredImagesCount) {
dispatch(
receivedPageOfImages({
categories: action.payload,
board_id: state.boards.selectedBoardId,
is_intermediate: false,
})
);
}
},
});
};

View File

@ -5,8 +5,10 @@ import {
Input, Input,
InputProps, InputProps,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { useAppDispatch } from 'app/store/storeHooks';
import { stopPastePropagation } from 'common/util/stopPastePropagation'; import { stopPastePropagation } from 'common/util/stopPastePropagation';
import { ChangeEvent, memo } from 'react'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { ChangeEvent, KeyboardEvent, memo, useCallback } from 'react';
interface IAIInputProps extends InputProps { interface IAIInputProps extends InputProps {
label?: string; label?: string;
@ -25,6 +27,25 @@ const IAIInput = (props: IAIInputProps) => {
...rest ...rest
} = props; } = props;
const dispatch = useAppDispatch();
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.shiftKey) {
dispatch(shiftKeyPressed(true));
}
},
[dispatch]
);
const handleKeyUp = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (!e.shiftKey) {
dispatch(shiftKeyPressed(false));
}
},
[dispatch]
);
return ( return (
<FormControl <FormControl
isInvalid={isInvalid} isInvalid={isInvalid}
@ -32,7 +53,12 @@ const IAIInput = (props: IAIInputProps) => {
{...formControlProps} {...formControlProps}
> >
{label !== '' && <FormLabel>{label}</FormLabel>} {label !== '' && <FormLabel>{label}</FormLabel>}
<Input {...rest} onPaste={stopPastePropagation} /> <Input
{...rest}
onPaste={stopPastePropagation}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
/>
</FormControl> </FormControl>
); );
}; };

View File

@ -1,7 +1,9 @@
import { Tooltip, useColorMode, useToken } from '@chakra-ui/react'; import { Tooltip, useColorMode, useToken } from '@chakra-ui/react';
import { MultiSelect, MultiSelectProps } from '@mantine/core'; import { MultiSelect, MultiSelectProps } from '@mantine/core';
import { useAppDispatch } from 'app/store/storeHooks';
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens'; import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
import { RefObject, memo } from 'react'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { KeyboardEvent, RefObject, memo, useCallback } from 'react';
import { mode } from 'theme/util/mode'; import { mode } from 'theme/util/mode';
type IAIMultiSelectProps = MultiSelectProps & { type IAIMultiSelectProps = MultiSelectProps & {
@ -11,6 +13,7 @@ type IAIMultiSelectProps = MultiSelectProps & {
const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => { const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
const { searchable = true, tooltip, inputRef, ...rest } = props; const { searchable = true, tooltip, inputRef, ...rest } = props;
const dispatch = useAppDispatch();
const { const {
base50, base50,
base100, base100,
@ -31,10 +34,30 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => {
const [boxShadow] = useToken('shadows', ['dark-lg']); const [boxShadow] = useToken('shadows', ['dark-lg']);
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.shiftKey) {
dispatch(shiftKeyPressed(true));
}
},
[dispatch]
);
const handleKeyUp = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (!e.shiftKey) {
dispatch(shiftKeyPressed(false));
}
},
[dispatch]
);
return ( return (
<Tooltip label={tooltip} placement="top" hasArrow isOpen={true}> <Tooltip label={tooltip} placement="top" hasArrow isOpen={true}>
<MultiSelect <MultiSelect
ref={inputRef} ref={inputRef}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
searchable={searchable} searchable={searchable}
styles={() => ({ styles={() => ({
label: { label: {

View File

@ -1,7 +1,9 @@
import { Tooltip, useColorMode, useToken } from '@chakra-ui/react'; import { Tooltip, useColorMode, useToken } from '@chakra-ui/react';
import { Select, SelectProps } from '@mantine/core'; import { Select, SelectProps } from '@mantine/core';
import { useAppDispatch } from 'app/store/storeHooks';
import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens'; import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens';
import { memo } from 'react'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { KeyboardEvent, memo, useCallback } from 'react';
import { mode } from 'theme/util/mode'; import { mode } from 'theme/util/mode';
export type IAISelectDataType = { export type IAISelectDataType = {
@ -16,6 +18,7 @@ type IAISelectProps = SelectProps & {
const IAIMantineSelect = (props: IAISelectProps) => { const IAIMantineSelect = (props: IAISelectProps) => {
const { searchable = true, tooltip, ...rest } = props; const { searchable = true, tooltip, ...rest } = props;
const dispatch = useAppDispatch();
const { const {
base50, base50,
base100, base100,
@ -36,11 +39,31 @@ const IAIMantineSelect = (props: IAISelectProps) => {
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.shiftKey) {
dispatch(shiftKeyPressed(true));
}
},
[dispatch]
);
const handleKeyUp = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (!e.shiftKey) {
dispatch(shiftKeyPressed(false));
}
},
[dispatch]
);
const [boxShadow] = useToken('shadows', ['dark-lg']); const [boxShadow] = useToken('shadows', ['dark-lg']);
return ( return (
<Tooltip label={tooltip} placement="top" hasArrow> <Tooltip label={tooltip} placement="top" hasArrow>
<Select <Select
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
searchable={searchable} searchable={searchable}
styles={() => ({ styles={() => ({
label: { label: {

View File

@ -14,10 +14,19 @@ import {
Tooltip, Tooltip,
TooltipProps, TooltipProps,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { useAppDispatch } from 'app/store/storeHooks';
import { stopPastePropagation } from 'common/util/stopPastePropagation'; import { stopPastePropagation } from 'common/util/stopPastePropagation';
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { clamp } from 'lodash-es'; import { clamp } from 'lodash-es';
import { FocusEvent, memo, useEffect, useState } from 'react'; import {
FocusEvent,
KeyboardEvent,
memo,
useCallback,
useEffect,
useState,
} from 'react';
const numberStringRegex = /^-?(0\.)?\.?$/; const numberStringRegex = /^-?(0\.)?\.?$/;
@ -60,6 +69,8 @@ const IAINumberInput = (props: Props) => {
...rest ...rest
} = props; } = props;
const dispatch = useAppDispatch();
/** /**
* Using a controlled input with a value that accepts decimals needs special * Using a controlled input with a value that accepts decimals needs special
* handling. If the user starts to type in "1.5", by the time they press the * handling. If the user starts to type in "1.5", by the time they press the
@ -109,6 +120,24 @@ const IAINumberInput = (props: Props) => {
onChange(clamped); onChange(clamped);
}; };
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.shiftKey) {
dispatch(shiftKeyPressed(true));
}
},
[dispatch]
);
const handleKeyUp = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (!e.shiftKey) {
dispatch(shiftKeyPressed(false));
}
},
[dispatch]
);
return ( return (
<Tooltip {...tooltipProps}> <Tooltip {...tooltipProps}>
<FormControl <FormControl
@ -128,7 +157,11 @@ const IAINumberInput = (props: Props) => {
{...rest} {...rest}
onPaste={stopPastePropagation} onPaste={stopPastePropagation}
> >
<NumberInputField {...numberInputFieldProps} /> <NumberInputField
{...numberInputFieldProps}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
/>
{showStepper && ( {showStepper && (
<NumberInputStepper> <NumberInputStepper>
<NumberIncrementStepper {...numberInputStepperProps} /> <NumberIncrementStepper {...numberInputStepperProps} />

View File

@ -26,9 +26,12 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { clamp } from 'lodash-es'; import { clamp } from 'lodash-es';
import { useAppDispatch } from 'app/store/storeHooks';
import { roundDownToMultiple } from 'common/util/roundDownToMultiple'; import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { import {
FocusEvent, FocusEvent,
KeyboardEvent,
memo, memo,
MouseEvent, MouseEvent,
useCallback, useCallback,
@ -56,7 +59,6 @@ export type IAIFullSliderProps = {
withInput?: boolean; withInput?: boolean;
isInteger?: boolean; isInteger?: boolean;
inputWidth?: string | number; inputWidth?: string | number;
inputReadOnly?: boolean;
withReset?: boolean; withReset?: boolean;
handleReset?: () => void; handleReset?: () => void;
tooltipSuffix?: string; tooltipSuffix?: string;
@ -90,7 +92,6 @@ const IAISlider = (props: IAIFullSliderProps) => {
withInput = false, withInput = false,
isInteger = false, isInteger = false,
inputWidth = 16, inputWidth = 16,
inputReadOnly = false,
withReset = false, withReset = false,
hideTooltip = false, hideTooltip = false,
isCompact = false, isCompact = false,
@ -109,7 +110,7 @@ const IAISlider = (props: IAIFullSliderProps) => {
sliderIAIIconButtonProps, sliderIAIIconButtonProps,
...rest ...rest
} = props; } = props;
const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const [localInputValue, setLocalInputValue] = useState< const [localInputValue, setLocalInputValue] = useState<
@ -152,6 +153,7 @@ const IAISlider = (props: IAIFullSliderProps) => {
); );
const handleInputChange = useCallback((v: number | string) => { const handleInputChange = useCallback((v: number | string) => {
console.log('input');
setLocalInputValue(v); setLocalInputValue(v);
}, []); }, []);
@ -168,6 +170,24 @@ const IAISlider = (props: IAIFullSliderProps) => {
} }
}, []); }, []);
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (e.shiftKey) {
dispatch(shiftKeyPressed(true));
}
},
[dispatch]
);
const handleKeyUp = useCallback(
(e: KeyboardEvent<HTMLInputElement>) => {
if (!e.shiftKey) {
dispatch(shiftKeyPressed(false));
}
},
[dispatch]
);
return ( return (
<FormControl <FormControl
onClick={forceInputBlur} onClick={forceInputBlur}
@ -311,7 +331,8 @@ const IAISlider = (props: IAIFullSliderProps) => {
{...sliderNumberInputProps} {...sliderNumberInputProps}
> >
<NumberInputField <NumberInputField
readOnly={inputReadOnly} onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
minWidth={inputWidth} minWidth={inputWidth}
{...sliderNumberInputFieldProps} {...sliderNumberInputFieldProps}
/> />

View File

@ -1,9 +1,38 @@
import { Textarea, TextareaProps, forwardRef } from '@chakra-ui/react'; import { Textarea, TextareaProps, forwardRef } from '@chakra-ui/react';
import { useAppDispatch } from 'app/store/storeHooks';
import { stopPastePropagation } from 'common/util/stopPastePropagation'; import { stopPastePropagation } from 'common/util/stopPastePropagation';
import { memo } from 'react'; import { shiftKeyPressed } from 'features/ui/store/hotkeysSlice';
import { KeyboardEvent, memo, useCallback } from 'react';
const IAITextarea = forwardRef((props: TextareaProps, ref) => { const IAITextarea = forwardRef((props: TextareaProps, ref) => {
return <Textarea ref={ref} onPaste={stopPastePropagation} {...props} />; const dispatch = useAppDispatch();
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLTextAreaElement>) => {
if (e.shiftKey) {
dispatch(shiftKeyPressed(true));
}
},
[dispatch]
);
const handleKeyUp = useCallback(
(e: KeyboardEvent<HTMLTextAreaElement>) => {
if (!e.shiftKey) {
dispatch(shiftKeyPressed(false));
}
},
[dispatch]
);
return (
<Textarea
ref={ref}
onPaste={stopPastePropagation}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
{...props}
/>
);
}); });
export default memo(IAITextarea); export default memo(IAITextarea);

View File

@ -235,7 +235,6 @@ const IAICanvasToolChooserOptions = () => {
withInput withInput
onChange={(newSize) => dispatch(setBrushSize(newSize))} onChange={(newSize) => dispatch(setBrushSize(newSize))}
sliderNumberInputProps={{ max: 500 }} sliderNumberInputProps={{ max: 500 }}
inputReadOnly={false}
/> />
</Flex> </Flex>
<IAIColorPicker <IAIColorPicker

View File

@ -1,4 +1,4 @@
import { Box, Flex, SystemStyleObject } from '@chakra-ui/react'; import { Box, Flex, Spinner, SystemStyleObject } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { skipToken } from '@reduxjs/toolkit/dist/query'; import { skipToken } from '@reduxjs/toolkit/dist/query';
import { import {
@ -8,7 +8,6 @@ import {
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAIDndImage from 'common/components/IAIDndImage'; import IAIDndImage from 'common/components/IAIDndImage';
import { IAILoadingImageFallback } from 'common/components/IAIImageFallback';
import { memo, useCallback, useMemo, useState } from 'react'; import { memo, useCallback, useMemo, useState } from 'react';
import { useGetImageDTOQuery } from 'services/api/endpoints/images'; import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import { PostUploadAction } from 'services/api/thunks/image'; import { PostUploadAction } from 'services/api/thunks/image';
@ -147,18 +146,28 @@ const ControlNetImagePreview = (props: Props) => {
/> />
</Box> </Box>
{pendingControlImages.includes(controlNetId) && ( {pendingControlImages.includes(controlNetId) && (
<Box <Flex
sx={{ sx={{
position: 'absolute', position: 'absolute',
top: 0, top: 0,
insetInlineStart: 0, insetInlineStart: 0,
w: 'full', w: 'full',
h: 'full', h: 'full',
objectFit: 'contain', alignItems: 'center',
justifyContent: 'center',
opacity: 0.8,
borderRadius: 'base',
bg: 'base.400',
_dark: {
bg: 'base.900',
},
}} }}
> >
<IAILoadingImageFallback image={controlImage} /> <Spinner
</Box> size="xl"
sx={{ color: 'base.100', _dark: { color: 'base.400' } }}
/>
</Flex>
)} )}
</Flex> </Flex>
); );

View File

@ -51,7 +51,6 @@ const ParamDynamicPromptsMaxPrompts = () => {
sliderNumberInputProps={{ max: inputMax }} sliderNumberInputProps={{ max: inputMax }}
withSliderMarks withSliderMarks
withInput withInput
inputReadOnly
withReset withReset
handleReset={handleReset} handleReset={handleReset}
/> />

View File

@ -8,20 +8,27 @@ import IAIButton from 'common/components/IAIButton';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice'; import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
import { systemSelector } from 'features/system/store/systemSelectors';
import { import { skipToken } from '@reduxjs/toolkit/dist/query';
activeTabNameSelector, import { useAppToaster } from 'app/components/Toaster';
uiSelector, import { stateSelector } from 'app/store/store';
} from 'features/ui/store/uiSelectors'; import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { DeleteImageButton } from 'features/imageDeletion/components/DeleteImageButton';
import { imageToDeleteSelected } from 'features/imageDeletion/store/imageDeletionSlice';
import FaceRestoreSettings from 'features/parameters/components/Parameters/FaceRestore/FaceRestoreSettings';
import UpscaleSettings from 'features/parameters/components/Parameters/Upscale/UpscaleSettings';
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
import { initialImageSelected } from 'features/parameters/store/actions';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { import {
setActiveTab, setActiveTab,
setShouldShowImageDetails, setShouldShowImageDetails,
setShouldShowProgressInViewer, setShouldShowProgressInViewer,
} from 'features/ui/store/uiSlice'; } from 'features/ui/store/uiSlice';
import { useCallback } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -38,21 +45,8 @@ import {
FaShare, FaShare,
FaShareAlt, FaShareAlt,
} from 'react-icons/fa'; } from 'react-icons/fa';
import { useCallback } from 'react';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
import { initialImageSelected } from 'features/parameters/store/actions';
import { sentImageToCanvas, sentImageToImg2Img } from '../store/actions';
import FaceRestoreSettings from 'features/parameters/components/Parameters/FaceRestore/FaceRestoreSettings';
import UpscaleSettings from 'features/parameters/components/Parameters/Upscale/UpscaleSettings';
import { useAppToaster } from 'app/components/Toaster';
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { stateSelector } from 'app/store/store';
import { useGetImageDTOQuery } from 'services/api/endpoints/images'; import { useGetImageDTOQuery } from 'services/api/endpoints/images';
import { skipToken } from '@reduxjs/toolkit/dist/query'; import { sentImageToCanvas, sentImageToImg2Img } from '../store/actions';
import { imageToDeleteSelected } from 'features/imageDeletion/store/imageDeletionSlice';
import { DeleteImageButton } from 'features/imageDeletion/components/DeleteImageButton';
const currentImageButtonsSelector = createSelector( const currentImageButtonsSelector = createSelector(
[stateSelector, activeTabNameSelector], [stateSelector, activeTabNameSelector],
@ -549,7 +543,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
/> />
</ButtonGroup> </ButtonGroup>
<ButtonGroup isAttached={true} isDisabled={shouldDisableToolbarButtons}> <ButtonGroup isAttached={true}>
<IAIIconButton <IAIIconButton
aria-label={t('settings.displayInProgress')} aria-label={t('settings.displayInProgress')}
tooltip={t('settings.displayInProgress')} tooltip={t('settings.displayInProgress')}

View File

@ -3,72 +3,47 @@ import {
Button, Button,
ButtonGroup, ButtonGroup,
Flex, Flex,
FlexProps,
Grid,
Skeleton,
Text, Text,
VStack, VStack,
forwardRef,
useColorMode, useColorMode,
useDisclosure, useDisclosure,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
import IAIIconButton from 'common/components/IAIIconButton'; import IAIIconButton from 'common/components/IAIIconButton';
import IAIPopover from 'common/components/IAIPopover'; import IAIPopover from 'common/components/IAIPopover';
import IAISimpleCheckbox from 'common/components/IAISimpleCheckbox';
import IAISlider from 'common/components/IAISlider'; import IAISlider from 'common/components/IAISlider';
import { import {
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
setGalleryView, setGalleryView,
} from 'features/gallery/store/gallerySlice'; } from 'features/gallery/store/gallerySlice';
import { togglePinGalleryPanel } from 'features/ui/store/uiSlice'; import { togglePinGalleryPanel } from 'features/ui/store/uiSlice';
import { useOverlayScrollbars } from 'overlayscrollbars-react';
import { import { ChangeEvent, memo, useCallback, useRef } from 'react';
ChangeEvent,
PropsWithChildren,
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs'; import { BsPinAngle, BsPinAngleFill } from 'react-icons/bs';
import { FaImage, FaServer, FaWrench } from 'react-icons/fa'; import { FaImage, FaServer, FaWrench } from 'react-icons/fa';
import GalleryImage from './GalleryImage';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import { ChevronUpIcon } from '@chakra-ui/icons';
import { createSelector } from '@reduxjs/toolkit'; import { createSelector } from '@reduxjs/toolkit';
import { RootState, stateSelector } from 'app/store/store'; import { stateSelector } from 'app/store/store';
import { VirtuosoGrid } from 'react-virtuoso';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { import {
ASSETS_CATEGORIES, ASSETS_CATEGORIES,
IMAGE_CATEGORIES, IMAGE_CATEGORIES,
imageCategoriesChanged, imageCategoriesChanged,
shouldAutoSwitchChanged, shouldAutoSwitchChanged,
selectFilteredImages,
} from 'features/gallery/store/gallerySlice'; } from 'features/gallery/store/gallerySlice';
import { receivedPageOfImages } from 'services/api/thunks/image';
import BoardsList from './Boards/BoardsList';
import { ChevronUpIcon } from '@chakra-ui/icons';
import { useListAllBoardsQuery } from 'services/api/endpoints/boards'; import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
import { mode } from 'theme/util/mode'; import { mode } from 'theme/util/mode';
import { ImageDTO } from 'services/api/types'; import BoardsList from './Boards/BoardsList';
import { IAINoContentFallback } from 'common/components/IAIImageFallback'; import ImageGalleryGrid from './ImageGalleryGrid';
const LOADING_IMAGE_ARRAY = Array(20).fill('loading');
const selector = createSelector( const selector = createSelector(
[stateSelector, selectFilteredImages], [stateSelector],
(state, filteredImages) => { (state) => {
const { const {
categories,
total: allImagesTotal,
isLoading,
selectedBoardId, selectedBoardId,
galleryImageMinimumWidth, galleryImageMinimumWidth,
galleryView, galleryView,
@ -76,13 +51,7 @@ const selector = createSelector(
} = state.gallery; } = state.gallery;
const { shouldPinGallery } = state.ui; const { shouldPinGallery } = state.ui;
const images = filteredImages as (ImageDTO | string)[];
return { return {
images: isLoading ? images.concat(LOADING_IMAGE_ARRAY) : images,
allImagesTotal,
isLoading,
categories,
selectedBoardId, selectedBoardId,
shouldPinGallery, shouldPinGallery,
galleryImageMinimumWidth, galleryImageMinimumWidth,
@ -97,28 +66,10 @@ const ImageGalleryContent = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const resizeObserverRef = useRef<HTMLDivElement>(null); const resizeObserverRef = useRef<HTMLDivElement>(null);
const rootRef = useRef(null);
const [scroller, setScroller] = useState<HTMLElement | null>(null);
const [initialize, osInstance] = useOverlayScrollbars({
defer: true,
options: {
scrollbars: {
visibility: 'auto',
autoHide: 'leave',
autoHideDelay: 1300,
theme: 'os-theme-dark',
},
overflow: { x: 'hidden' },
},
});
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const { const {
images,
isLoading,
allImagesTotal,
categories,
selectedBoardId, selectedBoardId,
shouldPinGallery, shouldPinGallery,
galleryImageMinimumWidth, galleryImageMinimumWidth,
@ -132,32 +83,6 @@ const ImageGalleryContent = () => {
}), }),
}); });
const filteredImagesTotal = useMemo(
() => selectedBoard?.image_count ?? allImagesTotal,
[allImagesTotal, selectedBoard?.image_count]
);
const areMoreAvailable = useMemo(() => {
return images.length < filteredImagesTotal;
}, [images.length, filteredImagesTotal]);
const handleLoadMoreImages = useCallback(() => {
dispatch(
receivedPageOfImages({
categories,
board_id: selectedBoardId,
is_intermediate: false,
})
);
}, [categories, dispatch, selectedBoardId]);
const handleEndReached = useMemo(() => {
if (areMoreAvailable && !isLoading) {
return handleLoadMoreImages;
}
return undefined;
}, [areMoreAvailable, handleLoadMoreImages, isLoading]);
const { isOpen: isBoardListOpen, onToggle } = useDisclosure(); const { isOpen: isBoardListOpen, onToggle } = useDisclosure();
const handleChangeGalleryImageMinimumWidth = (v: number) => { const handleChangeGalleryImageMinimumWidth = (v: number) => {
@ -169,28 +94,6 @@ const ImageGalleryContent = () => {
dispatch(requestCanvasRescale()); dispatch(requestCanvasRescale());
}; };
useEffect(() => {
const { current: root } = rootRef;
if (scroller && root) {
initialize({
target: root,
elements: {
viewport: scroller,
},
});
}
return () => osInstance()?.destroy();
}, [scroller, initialize, osInstance]);
useEffect(() => {
dispatch(
receivedPageOfImages({
categories: ['general'],
is_intermediate: false,
})
);
}, [dispatch]);
const handleClickImagesCategory = useCallback(() => { const handleClickImagesCategory = useCallback(() => {
dispatch(imageCategoriesChanged(IMAGE_CATEGORIES)); dispatch(imageCategoriesChanged(IMAGE_CATEGORIES));
dispatch(setGalleryView('images')); dispatch(setGalleryView('images'));
@ -314,80 +217,10 @@ const ImageGalleryContent = () => {
</Box> </Box>
</Box> </Box>
<Flex direction="column" gap={2} h="full" w="full"> <Flex direction="column" gap={2} h="full" w="full">
{images.length || areMoreAvailable ? ( <ImageGalleryGrid />
<>
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
<VirtuosoGrid
style={{ height: '100%' }}
data={images}
endReached={handleEndReached}
components={{
Item: ItemContainer,
List: ListContainer,
}}
scrollerRef={setScroller}
itemContent={(index, item) =>
typeof item === 'string' ? (
<Skeleton
sx={{ w: 'full', h: 'full', aspectRatio: '1/1' }}
/>
) : (
<GalleryImage
key={`${item.image_name}-${item.thumbnail_url}`}
imageDTO={item}
/>
)
}
/>
</Box>
<IAIButton
onClick={handleLoadMoreImages}
isDisabled={!areMoreAvailable}
isLoading={isLoading}
loadingText="Loading"
flexShrink={0}
>
{areMoreAvailable
? t('gallery.loadMore')
: t('gallery.allImagesLoaded')}
</IAIButton>
</>
) : (
<IAINoContentFallback
label={t('gallery.noImagesInGallery')}
icon={FaImage}
/>
)}
</Flex> </Flex>
</VStack> </VStack>
); );
}; };
type ItemContainerProps = PropsWithChildren & FlexProps;
const ItemContainer = forwardRef((props: ItemContainerProps, ref) => (
<Box className="item-container" ref={ref} p={1.5}>
{props.children}
</Box>
));
type ListContainerProps = PropsWithChildren & FlexProps;
const ListContainer = forwardRef((props: ListContainerProps, ref) => {
const galleryImageMinimumWidth = useAppSelector(
(state: RootState) => state.gallery.galleryImageMinimumWidth
);
return (
<Grid
{...props}
className="list-container"
ref={ref}
sx={{
gridTemplateColumns: `repeat(auto-fill, minmax(${galleryImageMinimumWidth}px, 1fr));`,
}}
>
{props.children}
</Grid>
);
});
export default memo(ImageGalleryContent); export default memo(ImageGalleryContent);

View File

@ -0,0 +1,226 @@
import {
Box,
Flex,
FlexProps,
Grid,
Skeleton,
Spinner,
forwardRef,
} from '@chakra-ui/react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';
import { IMAGE_LIMIT } from 'features/gallery/store/gallerySlice';
import { useOverlayScrollbars } from 'overlayscrollbars-react';
import {
PropsWithChildren,
memo,
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { useTranslation } from 'react-i18next';
import { FaImage } from 'react-icons/fa';
import GalleryImage from './GalleryImage';
import { createSelector } from '@reduxjs/toolkit';
import { RootState, stateSelector } from 'app/store/store';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
import { selectFilteredImages } from 'features/gallery/store/gallerySlice';
import { VirtuosoGrid } from 'react-virtuoso';
import { useListAllBoardsQuery } from 'services/api/endpoints/boards';
import { receivedPageOfImages } from 'services/api/thunks/image';
import { ImageDTO } from 'services/api/types';
const selector = createSelector(
[stateSelector, selectFilteredImages],
(state, filteredImages) => {
const {
categories,
total: allImagesTotal,
isLoading,
isFetching,
selectedBoardId,
} = state.gallery;
let images = filteredImages as (ImageDTO | 'loading')[];
if (!isLoading && isFetching) {
// loading, not not the initial load
images = images.concat(Array(IMAGE_LIMIT).fill('loading'));
}
return {
images,
allImagesTotal,
isLoading,
categories,
selectedBoardId,
};
},
defaultSelectorOptions
);
const ImageGalleryGrid = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const rootRef = useRef(null);
const [scroller, setScroller] = useState<HTMLElement | null>(null);
const [initialize, osInstance] = useOverlayScrollbars({
defer: true,
options: {
scrollbars: {
visibility: 'auto',
autoHide: 'leave',
autoHideDelay: 1300,
theme: 'os-theme-dark',
},
overflow: { x: 'hidden' },
},
});
const { images, isLoading, allImagesTotal, categories, selectedBoardId } =
useAppSelector(selector);
const { selectedBoard } = useListAllBoardsQuery(undefined, {
selectFromResult: ({ data }) => ({
selectedBoard: data?.find((b) => b.board_id === selectedBoardId),
}),
});
const filteredImagesTotal = useMemo(
() => selectedBoard?.image_count ?? allImagesTotal,
[allImagesTotal, selectedBoard?.image_count]
);
const areMoreAvailable = useMemo(() => {
return images.length < filteredImagesTotal;
}, [images.length, filteredImagesTotal]);
const handleLoadMoreImages = useCallback(() => {
dispatch(
receivedPageOfImages({
categories,
board_id: selectedBoardId,
is_intermediate: false,
})
);
}, [categories, dispatch, selectedBoardId]);
const handleEndReached = useMemo(() => {
if (areMoreAvailable && !isLoading) {
return handleLoadMoreImages;
}
return undefined;
}, [areMoreAvailable, handleLoadMoreImages, isLoading]);
useEffect(() => {
const { current: root } = rootRef;
if (scroller && root) {
initialize({
target: root,
elements: {
viewport: scroller,
},
});
}
return () => osInstance()?.destroy();
}, [scroller, initialize, osInstance]);
if (isLoading) {
return (
<Flex
sx={{
w: 'full',
h: 'full',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Spinner
size="xl"
sx={{ color: 'base.300', _dark: { color: 'base.700' } }}
/>
</Flex>
);
}
if (images.length) {
return (
<>
<Box ref={rootRef} data-overlayscrollbars="" h="100%">
<VirtuosoGrid
style={{ height: '100%' }}
data={images}
endReached={handleEndReached}
components={{
Item: ItemContainer,
List: ListContainer,
}}
scrollerRef={setScroller}
itemContent={(index, item) =>
typeof item === 'string' ? (
<Skeleton sx={{ w: 'full', h: 'full', aspectRatio: '1/1' }} />
) : (
<GalleryImage
key={`${item.image_name}-${item.thumbnail_url}`}
imageDTO={item}
/>
)
}
/>
</Box>
<IAIButton
onClick={handleLoadMoreImages}
isDisabled={!areMoreAvailable}
isLoading={isLoading}
loadingText="Loading"
flexShrink={0}
>
{areMoreAvailable
? t('gallery.loadMore')
: t('gallery.allImagesLoaded')}
</IAIButton>
</>
);
}
return (
<IAINoContentFallback
label={t('gallery.noImagesInGallery')}
icon={FaImage}
/>
);
};
type ItemContainerProps = PropsWithChildren & FlexProps;
const ItemContainer = forwardRef((props: ItemContainerProps, ref) => (
<Box className="item-container" ref={ref} p={1.5}>
{props.children}
</Box>
));
type ListContainerProps = PropsWithChildren & FlexProps;
const ListContainer = forwardRef((props: ListContainerProps, ref) => {
const galleryImageMinimumWidth = useAppSelector(
(state: RootState) => state.gallery.galleryImageMinimumWidth
);
return (
<Grid
{...props}
className="list-container"
ref={ref}
sx={{
gridTemplateColumns: `repeat(auto-fill, minmax(${galleryImageMinimumWidth}px, 1fr));`,
}}
>
{props.children}
</Grid>
);
});
export default memo(ImageGalleryGrid);

View File

@ -11,5 +11,8 @@ export const galleryPersistDenylist: (keyof typeof initialGalleryState)[] = [
'limit', 'limit',
'offset', 'offset',
'selectedBoardId', 'selectedBoardId',
'categories',
'galleryView',
'total', 'total',
'isInitialized',
]; ];

View File

@ -28,17 +28,22 @@ export const ASSETS_CATEGORIES: ImageCategory[] = [
'other', 'other',
]; ];
export const INITIAL_IMAGE_LIMIT = 100;
export const IMAGE_LIMIT = 20;
type AdditionaGalleryState = { type AdditionaGalleryState = {
offset: number; offset: number;
limit: number; limit: number;
total: number; total: number;
isLoading: boolean; isLoading: boolean;
isFetching: boolean;
categories: ImageCategory[]; categories: ImageCategory[];
selectedBoardId?: string; selectedBoardId?: string;
selection: string[]; selection: string[];
shouldAutoSwitch: boolean; shouldAutoSwitch: boolean;
galleryImageMinimumWidth: number; galleryImageMinimumWidth: number;
galleryView: 'images' | 'assets' | 'boards'; galleryView: 'images' | 'assets';
isInitialized: boolean;
}; };
export const initialGalleryState = export const initialGalleryState =
@ -47,11 +52,13 @@ export const initialGalleryState =
limit: 0, limit: 0,
total: 0, total: 0,
isLoading: true, isLoading: true,
isFetching: true,
categories: IMAGE_CATEGORIES, categories: IMAGE_CATEGORIES,
selection: [], selection: [],
shouldAutoSwitch: true, shouldAutoSwitch: true,
galleryImageMinimumWidth: 64, galleryImageMinimumWidth: 96,
galleryView: 'images', galleryView: 'images',
isInitialized: false,
}); });
export const gallerySlice = createSlice({ export const gallerySlice = createSlice({
@ -65,6 +72,8 @@ export const gallerySlice = createSlice({
action.payload.image_category === 'general' action.payload.image_category === 'general'
) { ) {
state.selection = [action.payload.image_name]; state.selection = [action.payload.image_name];
state.galleryView = 'images';
state.categories = IMAGE_CATEGORIES;
} }
}, },
imageUpdatedOne: (state, action: PayloadAction<Update<ImageDTO>>) => { imageUpdatedOne: (state, action: PayloadAction<Update<ImageDTO>>) => {
@ -128,38 +137,33 @@ export const gallerySlice = createSlice({
setGalleryImageMinimumWidth: (state, action: PayloadAction<number>) => { setGalleryImageMinimumWidth: (state, action: PayloadAction<number>) => {
state.galleryImageMinimumWidth = action.payload; state.galleryImageMinimumWidth = action.payload;
}, },
setGalleryView: ( setGalleryView: (state, action: PayloadAction<'images' | 'assets'>) => {
state,
action: PayloadAction<'images' | 'assets' | 'boards'>
) => {
state.galleryView = action.payload; state.galleryView = action.payload;
}, },
boardIdSelected: (state, action: PayloadAction<string | undefined>) => { boardIdSelected: (state, action: PayloadAction<string | undefined>) => {
state.selectedBoardId = action.payload; state.selectedBoardId = action.payload;
}, },
isLoadingChanged: (state, action: PayloadAction<boolean>) => {
state.isLoading = action.payload;
},
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(receivedPageOfImages.pending, (state) => { builder.addCase(receivedPageOfImages.pending, (state) => {
state.isLoading = true; state.isFetching = true;
}); });
builder.addCase(receivedPageOfImages.rejected, (state) => { builder.addCase(receivedPageOfImages.rejected, (state) => {
state.isLoading = false; state.isFetching = false;
}); });
builder.addCase(receivedPageOfImages.fulfilled, (state, action) => { builder.addCase(receivedPageOfImages.fulfilled, (state, action) => {
state.isLoading = false; state.isFetching = false;
const { board_id, categories, image_origin, is_intermediate } = const { board_id, categories, image_origin, is_intermediate } =
action.meta.arg; action.meta.arg;
const { items, offset, limit, total } = action.payload; const { items, offset, limit, total } = action.payload;
const transformedItems = items.map((item) => ({ imagesAdapter.upsertMany(state, items);
...item,
isSelected: false,
}));
imagesAdapter.upsertMany(state, transformedItems); if (state.selection.length === 0 && items.length) {
if (state.selection.length === 0) {
state.selection = [items[0].image_name]; state.selection = [items[0].image_name];
} }
@ -170,7 +174,6 @@ export const gallerySlice = createSlice({
} }
state.offset = offset; state.offset = offset;
state.limit = limit;
state.total = total; state.total = total;
}); });
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => { builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
@ -213,6 +216,7 @@ export const {
setGalleryImageMinimumWidth, setGalleryImageMinimumWidth,
setGalleryView, setGalleryView,
boardIdSelected, boardIdSelected,
isLoadingChanged,
} = gallerySlice.actions; } = gallerySlice.actions;
export default gallerySlice.reducer; export default gallerySlice.reducer;

View File

@ -1,6 +1,7 @@
import { log } from 'app/logging/useLogger'; import { log } from 'app/logging/useLogger';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types'; import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
import { import {
ImageDTO, ImageDTO,
ImageResizeInvocation, ImageResizeInvocation,
@ -42,9 +43,8 @@ export const buildCanvasImageToImageGraph = (
steps, steps,
img2imgStrength: strength, img2imgStrength: strength,
clipSkip, clipSkip,
iterations, shouldUseCpuNoise,
seed, shouldUseNoiseSettings,
shouldRandomizeSeed,
} = state.generation; } = state.generation;
// The bounding box determines width and height, not the width and height params // The bounding box determines width and height, not the width and height params
@ -52,6 +52,10 @@ export const buildCanvasImageToImageGraph = (
const model = modelIdToMainModelField(currentModel?.id || ''); const model = modelIdToMainModelField(currentModel?.id || '');
const use_cpu = shouldUseNoiseSettings
? shouldUseCpuNoise
: initialGenerationState.shouldUseCpuNoise;
/** /**
* The easiest way to build linear graphs is to do it in the node editor, then copy and paste the * The easiest way to build linear graphs is to do it in the node editor, then copy and paste the
* full graph here as a template. Then use the parameters from app state and set friendlier node * full graph here as a template. Then use the parameters from app state and set friendlier node
@ -78,6 +82,7 @@ export const buildCanvasImageToImageGraph = (
[NOISE]: { [NOISE]: {
type: 'noise', type: 'noise',
id: NOISE, id: NOISE,
use_cpu,
}, },
[MAIN_MODEL_LOADER]: { [MAIN_MODEL_LOADER]: {
type: 'main_model_loader', type: 'main_model_loader',

View File

@ -1,5 +1,6 @@
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types'; import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
import { addControlNetToLinearGraph } from '../addControlNetToLinearGraph'; import { addControlNetToLinearGraph } from '../addControlNetToLinearGraph';
import { modelIdToMainModelField } from '../modelIdToMainModelField'; import { modelIdToMainModelField } from '../modelIdToMainModelField';
import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph'; import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
@ -30,9 +31,8 @@ export const buildCanvasTextToImageGraph = (
scheduler, scheduler,
steps, steps,
clipSkip, clipSkip,
iterations, shouldUseCpuNoise,
seed, shouldUseNoiseSettings,
shouldRandomizeSeed,
} = state.generation; } = state.generation;
// The bounding box determines width and height, not the width and height params // The bounding box determines width and height, not the width and height params
@ -40,6 +40,10 @@ export const buildCanvasTextToImageGraph = (
const model = modelIdToMainModelField(currentModel?.id || ''); const model = modelIdToMainModelField(currentModel?.id || '');
const use_cpu = shouldUseNoiseSettings
? shouldUseCpuNoise
: initialGenerationState.shouldUseCpuNoise;
/** /**
* The easiest way to build linear graphs is to do it in the node editor, then copy and paste the * The easiest way to build linear graphs is to do it in the node editor, then copy and paste the
* full graph here as a template. Then use the parameters from app state and set friendlier node * full graph here as a template. Then use the parameters from app state and set friendlier node
@ -68,6 +72,7 @@ export const buildCanvasTextToImageGraph = (
id: NOISE, id: NOISE,
width, width,
height, height,
use_cpu,
}, },
[TEXT_TO_LATENTS]: { [TEXT_TO_LATENTS]: {
type: 't2l', type: 't2l',

View File

@ -1,6 +1,7 @@
import { log } from 'app/logging/useLogger'; import { log } from 'app/logging/useLogger';
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types'; import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
import { import {
ImageCollectionInvocation, ImageCollectionInvocation,
ImageResizeInvocation, ImageResizeInvocation,
@ -48,6 +49,8 @@ export const buildLinearImageToImageGraph = (
width, width,
height, height,
clipSkip, clipSkip,
shouldUseCpuNoise,
shouldUseNoiseSettings,
} = state.generation; } = state.generation;
const { const {
@ -75,6 +78,10 @@ export const buildLinearImageToImageGraph = (
const model = modelIdToMainModelField(currentModel?.id || ''); const model = modelIdToMainModelField(currentModel?.id || '');
const use_cpu = shouldUseNoiseSettings
? shouldUseCpuNoise
: initialGenerationState.shouldUseCpuNoise;
// copy-pasted graph from node editor, filled in with state values & friendly node ids // copy-pasted graph from node editor, filled in with state values & friendly node ids
const graph: NonNullableGraph = { const graph: NonNullableGraph = {
id: IMAGE_TO_IMAGE_GRAPH, id: IMAGE_TO_IMAGE_GRAPH,
@ -102,6 +109,7 @@ export const buildLinearImageToImageGraph = (
[NOISE]: { [NOISE]: {
type: 'noise', type: 'noise',
id: NOISE, id: NOISE,
use_cpu,
}, },
[LATENTS_TO_IMAGE]: { [LATENTS_TO_IMAGE]: {
type: 'l2i', type: 'l2i',

View File

@ -1,5 +1,6 @@
import { RootState } from 'app/store/store'; import { RootState } from 'app/store/store';
import { NonNullableGraph } from 'features/nodes/types/types'; import { NonNullableGraph } from 'features/nodes/types/types';
import { initialGenerationState } from 'features/parameters/store/generationSlice';
import { addControlNetToLinearGraph } from '../addControlNetToLinearGraph'; import { addControlNetToLinearGraph } from '../addControlNetToLinearGraph';
import { modelIdToMainModelField } from '../modelIdToMainModelField'; import { modelIdToMainModelField } from '../modelIdToMainModelField';
import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph'; import { addDynamicPromptsToGraph } from './addDynamicPromptsToGraph';
@ -29,10 +30,16 @@ export const buildLinearTextToImageGraph = (
width, width,
height, height,
clipSkip, clipSkip,
shouldUseCpuNoise,
shouldUseNoiseSettings,
} = state.generation; } = state.generation;
const model = modelIdToMainModelField(currentModel?.id || ''); const model = modelIdToMainModelField(currentModel?.id || '');
const use_cpu = shouldUseNoiseSettings
? shouldUseCpuNoise
: initialGenerationState.shouldUseCpuNoise;
/** /**
* The easiest way to build linear graphs is to do it in the node editor, then copy and paste the * The easiest way to build linear graphs is to do it in the node editor, then copy and paste the
* full graph here as a template. Then use the parameters from app state and set friendlier node * full graph here as a template. Then use the parameters from app state and set friendlier node
@ -71,6 +78,7 @@ export const buildLinearTextToImageGraph = (
id: NOISE, id: NOISE,
width, width,
height, height,
use_cpu,
}, },
[TEXT_TO_LATENTS]: { [TEXT_TO_LATENTS]: {
type: 't2l', type: 't2l',

View File

@ -59,7 +59,6 @@ const ParamBoundingBoxWidth = () => {
sliderNumberInputProps={{ max: 4096 }} sliderNumberInputProps={{ max: 4096 }}
withSliderMarks withSliderMarks
withInput withInput
inputReadOnly
withReset withReset
handleReset={handleResetHeight} handleReset={handleResetHeight}
/> />

View File

@ -59,7 +59,6 @@ const ParamBoundingBoxWidth = () => {
sliderNumberInputProps={{ max: 4096 }} sliderNumberInputProps={{ max: 4096 }}
withSliderMarks withSliderMarks
withInput withInput
inputReadOnly
withReset withReset
handleReset={handleResetWidth} handleReset={handleResetWidth}
/> />

View File

@ -58,7 +58,6 @@ const ParamScaledHeight = () => {
sliderNumberInputProps={{ max: 4096 }} sliderNumberInputProps={{ max: 4096 }}
withSliderMarks withSliderMarks
withInput withInput
inputReadOnly
withReset withReset
handleReset={handleResetScaledHeight} handleReset={handleResetScaledHeight}
/> />

View File

@ -56,7 +56,6 @@ const ParamScaledWidth = () => {
sliderNumberInputProps={{ max: 4096 }} sliderNumberInputProps={{ max: 4096 }}
withSliderMarks withSliderMarks
withInput withInput
inputReadOnly
withReset withReset
handleReset={handleResetScaledWidth} handleReset={handleResetScaledWidth}
/> />

View File

@ -0,0 +1,39 @@
import { createSelector } from '@reduxjs/toolkit';
import { stateSelector } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch';
import { shouldUseCpuNoiseChanged } from 'features/parameters/store/generationSlice';
import { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
stateSelector,
(state) => {
const { shouldUseNoiseSettings, shouldUseCpuNoise } = state.generation;
return {
isDisabled: !shouldUseNoiseSettings,
shouldUseCpuNoise,
};
},
defaultSelectorOptions
);
export const ParamCpuNoiseToggle = () => {
const dispatch = useAppDispatch();
const { isDisabled, shouldUseCpuNoise } = useAppSelector(selector);
const { t } = useTranslation();
const handleChange = (e: ChangeEvent<HTMLInputElement>) =>
dispatch(shouldUseCpuNoiseChanged(e.target.checked));
return (
<IAISwitch
isDisabled={isDisabled}
label="Use CPU Noise"
isChecked={shouldUseCpuNoise}
onChange={handleChange}
/>
);
};

View File

@ -7,6 +7,7 @@ import IAICollapse from 'common/components/IAICollapse';
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { memo } from 'react'; import { memo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ParamCpuNoiseToggle } from './ParamCpuNoise';
import ParamNoiseThreshold from './ParamNoiseThreshold'; import ParamNoiseThreshold from './ParamNoiseThreshold';
import { ParamNoiseToggle } from './ParamNoiseToggle'; import { ParamNoiseToggle } from './ParamNoiseToggle';
import ParamPerlinNoise from './ParamPerlinNoise'; import ParamPerlinNoise from './ParamPerlinNoise';
@ -40,6 +41,7 @@ const ParamNoiseCollapse = () => {
> >
<Flex sx={{ gap: 2, flexDirection: 'column' }}> <Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamNoiseToggle /> <ParamNoiseToggle />
<ParamCpuNoiseToggle />
<ParamPerlinNoise /> <ParamPerlinNoise />
<ParamNoiseThreshold /> <ParamNoiseThreshold />
</Flex> </Flex>

View File

@ -55,6 +55,7 @@ export interface GenerationState {
seamlessXAxis: boolean; seamlessXAxis: boolean;
seamlessYAxis: boolean; seamlessYAxis: boolean;
clipSkip: number; clipSkip: number;
shouldUseCpuNoise: boolean;
} }
export const initialGenerationState: GenerationState = { export const initialGenerationState: GenerationState = {
@ -90,6 +91,7 @@ export const initialGenerationState: GenerationState = {
seamlessXAxis: false, seamlessXAxis: false,
seamlessYAxis: false, seamlessYAxis: false,
clipSkip: 0, clipSkip: 0,
shouldUseCpuNoise: true,
}; };
const initialState: GenerationState = initialGenerationState; const initialState: GenerationState = initialGenerationState;
@ -239,6 +241,9 @@ export const generationSlice = createSlice({
setClipSkip: (state, action: PayloadAction<number>) => { setClipSkip: (state, action: PayloadAction<number>) => {
state.clipSkip = action.payload; state.clipSkip = action.payload;
}, },
shouldUseCpuNoiseChanged: (state, action: PayloadAction<boolean>) => {
state.shouldUseCpuNoise = action.payload;
},
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(configChanged, (state, action) => { builder.addCase(configChanged, (state, action) => {
@ -298,6 +303,7 @@ export const {
setSeamlessXAxis, setSeamlessXAxis,
setSeamlessYAxis, setSeamlessYAxis,
setClipSkip, setClipSkip,
shouldUseCpuNoiseChanged,
} = generationSlice.actions; } = generationSlice.actions;
export default generationSlice.reducer; export default generationSlice.reducer;

View File

@ -1,15 +1,17 @@
import { Flex, Text, Image } from '@chakra-ui/react'; import { Flex, Image, Text } from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import InvokeAILogoImage from 'assets/images/logo.png'; import InvokeAILogoImage from 'assets/images/logo.png';
import { AnimatePresence, motion } from 'framer-motion';
import { useRef } from 'react';
import { useHoverDirty } from 'react-use';
import { useGetAppVersionQuery } from 'services/api/endpoints/appInfo';
const InvokeAILogoComponent = () => { const InvokeAILogoComponent = () => {
const appVersion = useAppSelector( const { data: appVersion } = useGetAppVersionQuery();
(state: RootState) => state.system.app_version const ref = useRef(null);
); const isHovered = useHoverDirty(ref);
return ( return (
<Flex alignItems="center" gap={3} ps={1}> <Flex alignItems="center" gap={3} ps={1} ref={ref}>
<Image <Image
src={InvokeAILogoImage} src={InvokeAILogoImage}
alt="invoke-ai-logo" alt="invoke-ai-logo"
@ -21,19 +23,40 @@ const InvokeAILogoComponent = () => {
userSelect: 'none', userSelect: 'none',
}} }}
/> />
<Flex sx={{ gap: 3 }}> <Flex sx={{ gap: 3, alignItems: 'center' }}>
<Text sx={{ fontSize: 'xl', userSelect: 'none' }}> <Text sx={{ fontSize: 'xl', userSelect: 'none' }}>
invoke <strong>ai</strong> invoke <strong>ai</strong>
</Text> </Text>
<AnimatePresence>
{isHovered && appVersion && (
<motion.div
key="statusText"
initial={{
opacity: 0,
}}
animate={{
opacity: 1,
transition: { duration: 0.15 },
}}
exit={{
opacity: 0,
transition: { delay: 0.8 },
}}
>
<Text <Text
sx={{ sx={{
fontWeight: 300, fontWeight: 600,
marginTop: 1, marginTop: 1,
color: 'base.300',
fontSize: 14,
}} }}
variant="subtext" variant="subtext"
> >
{appVersion} {appVersion.version}
</Text> </Text>
</motion.div>
)}
</AnimatePresence>
</Flex> </Flex>
</Flex> </Flex>
); );

View File

@ -48,7 +48,6 @@ export default function UnifiedCanvasBrushSize() {
withInput withInput
onChange={(newSize) => dispatch(setBrushSize(newSize))} onChange={(newSize) => dispatch(setBrushSize(newSize))}
sliderNumberInputProps={{ max: 500 }} sliderNumberInputProps={{ max: 500 }}
inputReadOnly={false}
isCompact isCompact
/> />
); );

View File

@ -0,0 +1,15 @@
import { api } from '..';
import { AppVersion } from '../types';
export const appInfoApi = api.injectEndpoints({
endpoints: (build) => ({
getAppVersion: build.query<AppVersion, void>({
query: () => ({
url: `app/version`,
method: 'GET',
}),
}),
}),
});
export const { useGetAppVersionQuery } = appInfoApi;

View File

@ -205,6 +205,10 @@ export type paths = {
*/ */
get: operations["list_board_images"]; get: operations["list_board_images"];
}; };
"/api/v1/app/version": {
/** Get Version */
get: operations["app_version"];
};
}; };
export type webhooks = Record<string, never>; export type webhooks = Record<string, never>;
@ -246,6 +250,14 @@ export type components = {
*/ */
b?: number; b?: number;
}; };
/**
* AppVersion
* @description App Version Response
*/
AppVersion: {
/** Version */
version: string;
};
/** /**
* BaseModelType * BaseModelType
* @description An enumeration. * @description An enumeration.
@ -1046,7 +1058,7 @@ export type components = {
* @description The nodes in this graph * @description The nodes in this graph
*/ */
nodes?: { 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"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | 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"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | 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; [key: string]: (components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | 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"]["CvInpaintInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["UpscaleInvocation"] | 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 * Edges
@ -1089,7 +1101,7 @@ export type components = {
* @description The results of node executions * @description The results of node executions
*/ */
results: { results: {
[key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined; [key: string]: (components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["VaeLoaderOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined;
}; };
/** /**
* Errors * Errors
@ -3098,7 +3110,7 @@ export type components = {
/** ModelsList */ /** ModelsList */
ModelsList: { ModelsList: {
/** Models */ /** Models */
models: (components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"])[]; models: (components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"])[];
}; };
/** /**
* MultiplyInvocation * MultiplyInvocation
@ -4535,7 +4547,7 @@ export type operations = {
}; };
requestBody: { requestBody: {
content: { 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"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | 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"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | 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"]; "application/json": components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | 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"]["CvInpaintInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["UpscaleInvocation"] | 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: { responses: {
@ -4572,7 +4584,7 @@ export type operations = {
}; };
requestBody: { requestBody: {
content: { 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"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | 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"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | 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"]; "application/json": components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ClipSkipInvocation"] | 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"]["CvInpaintInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["UpscaleInvocation"] | 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: { responses: {
@ -4805,7 +4817,7 @@ export type operations = {
/** @description The model imported successfully */ /** @description The model imported successfully */
201: { 201: {
content: { content: {
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"]; "application/json": components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"];
}; };
}; };
/** @description The model could not be found */ /** @description The model could not be found */
@ -4873,14 +4885,14 @@ export type operations = {
}; };
requestBody: { requestBody: {
content: { content: {
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"]; "application/json": components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"];
}; };
}; };
responses: { responses: {
/** @description The model was updated successfully */ /** @description The model was updated successfully */
200: { 200: {
content: { content: {
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"]; "application/json": components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"];
}; };
}; };
/** @description Bad request */ /** @description Bad request */
@ -4914,7 +4926,7 @@ export type operations = {
/** @description Model converted successfully */ /** @description Model converted successfully */
200: { 200: {
content: { content: {
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"]; "application/json": components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"];
}; };
}; };
/** @description Bad request */ /** @description Bad request */
@ -4949,7 +4961,7 @@ export type operations = {
/** @description Model converted successfully */ /** @description Model converted successfully */
200: { 200: {
content: { content: {
"application/json": components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"]; "application/json": components["schemas"]["StableDiffusion1ModelCheckpointConfig"] | components["schemas"]["StableDiffusion1ModelDiffusersConfig"] | components["schemas"]["VaeModelConfig"] | components["schemas"]["LoRAModelConfig"] | components["schemas"]["ControlNetModelConfig"] | components["schemas"]["TextualInversionModelConfig"] | components["schemas"]["StableDiffusion2ModelDiffusersConfig"] | components["schemas"]["StableDiffusion2ModelCheckpointConfig"];
}; };
}; };
/** @description Incompatible models */ /** @description Incompatible models */
@ -5427,4 +5439,15 @@ export type operations = {
}; };
}; };
}; };
/** Get Version */
app_version: {
responses: {
/** @description Successful Response */
200: {
content: {
"application/json": components["schemas"]["AppVersion"];
};
};
};
};
}; };

View File

@ -8,6 +8,9 @@ type schemas = components['schemas'];
*/ */
type TypeReq<T> = O.Required<T, 'type'>; type TypeReq<T> = O.Required<T, 'type'>;
// App Info
export type AppVersion = components['schemas']['AppVersion'];
// Images // Images
export type ImageDTO = components['schemas']['ImageDTO']; export type ImageDTO = components['schemas']['ImageDTO'];
export type BoardDTO = components['schemas']['BoardDTO']; export type BoardDTO = components['schemas']['BoardDTO'];

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
__version__ = "3.0.0-rc1" __version__ = "3.0.0+b2"