mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
merge with main
This commit is contained in:
commit
bd9786564c
18
invokeai/app/api/routers/app_info.py
Normal file
18
invokeai/app/api/routers/app_info.py
Normal 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__)
|
@ -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():
|
||||||
|
199
invokeai/frontend/web/dist/assets/App-9658ed7f.js
vendored
199
invokeai/frontend/web/dist/assets/App-9658ed7f.js
vendored
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
125
invokeai/frontend/web/dist/assets/index-43f18910.js
vendored
125
invokeai/frontend/web/dist/assets/index-43f18910.js
vendored
File diff suppressed because one or more lines are too long
2
invokeai/frontend/web/dist/index.html
vendored
2
invokeai/frontend/web/dist/index.html
vendored
@ -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">
|
||||||
|
@ -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">
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -9,4 +9,5 @@ export const actionsDenylist = [
|
|||||||
'canvas/addPointToCurrentLine',
|
'canvas/addPointToCurrentLine',
|
||||||
'socket/socketGeneratorProgress',
|
'socket/socketGeneratorProgress',
|
||||||
'socket/appSocketGeneratorProgress',
|
'socket/appSocketGeneratorProgress',
|
||||||
|
'hotkeys/shiftKeyPressed',
|
||||||
];
|
];
|
||||||
|
@ -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();
|
||||||
|
@ -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));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
@ -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,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -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: {
|
||||||
|
@ -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: {
|
||||||
|
@ -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} />
|
||||||
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -51,7 +51,6 @@ const ParamDynamicPromptsMaxPrompts = () => {
|
|||||||
sliderNumberInputProps={{ max: inputMax }}
|
sliderNumberInputProps={{ max: inputMax }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
inputReadOnly
|
|
||||||
withReset
|
withReset
|
||||||
handleReset={handleReset}
|
handleReset={handleReset}
|
||||||
/>
|
/>
|
||||||
|
@ -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')}
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
@ -11,5 +11,8 @@ export const galleryPersistDenylist: (keyof typeof initialGalleryState)[] = [
|
|||||||
'limit',
|
'limit',
|
||||||
'offset',
|
'offset',
|
||||||
'selectedBoardId',
|
'selectedBoardId',
|
||||||
|
'categories',
|
||||||
|
'galleryView',
|
||||||
'total',
|
'total',
|
||||||
|
'isInitialized',
|
||||||
];
|
];
|
||||||
|
@ -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;
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -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',
|
||||||
|
@ -59,7 +59,6 @@ const ParamBoundingBoxWidth = () => {
|
|||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
inputReadOnly
|
|
||||||
withReset
|
withReset
|
||||||
handleReset={handleResetHeight}
|
handleReset={handleResetHeight}
|
||||||
/>
|
/>
|
||||||
|
@ -59,7 +59,6 @@ const ParamBoundingBoxWidth = () => {
|
|||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
inputReadOnly
|
|
||||||
withReset
|
withReset
|
||||||
handleReset={handleResetWidth}
|
handleReset={handleResetWidth}
|
||||||
/>
|
/>
|
||||||
|
@ -58,7 +58,6 @@ const ParamScaledHeight = () => {
|
|||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
inputReadOnly
|
|
||||||
withReset
|
withReset
|
||||||
handleReset={handleResetScaledHeight}
|
handleReset={handleResetScaledHeight}
|
||||||
/>
|
/>
|
||||||
|
@ -56,7 +56,6 @@ const ParamScaledWidth = () => {
|
|||||||
sliderNumberInputProps={{ max: 4096 }}
|
sliderNumberInputProps={{ max: 4096 }}
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withInput
|
withInput
|
||||||
inputReadOnly
|
|
||||||
withReset
|
withReset
|
||||||
handleReset={handleResetScaledWidth}
|
handleReset={handleResetScaledWidth}
|
||||||
/>
|
/>
|
||||||
|
@ -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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -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>
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
<Text
|
<AnimatePresence>
|
||||||
sx={{
|
{isHovered && appVersion && (
|
||||||
fontWeight: 300,
|
<motion.div
|
||||||
marginTop: 1,
|
key="statusText"
|
||||||
}}
|
initial={{
|
||||||
variant="subtext"
|
opacity: 0,
|
||||||
>
|
}}
|
||||||
{appVersion}
|
animate={{
|
||||||
</Text>
|
opacity: 1,
|
||||||
|
transition: { duration: 0.15 },
|
||||||
|
}}
|
||||||
|
exit={{
|
||||||
|
opacity: 0,
|
||||||
|
transition: { delay: 0.8 },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
sx={{
|
||||||
|
fontWeight: 600,
|
||||||
|
marginTop: 1,
|
||||||
|
color: 'base.300',
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
variant="subtext"
|
||||||
|
>
|
||||||
|
{appVersion.version}
|
||||||
|
</Text>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@ -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
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
15
invokeai/frontend/web/src/services/api/endpoints/appInfo.ts
Normal file
15
invokeai/frontend/web/src/services/api/endpoints/appInfo.ts
Normal 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;
|
@ -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"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -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
@ -1 +1 @@
|
|||||||
__version__ = "3.0.0-rc1"
|
__version__ = "3.0.0+b2"
|
||||||
|
Loading…
Reference in New Issue
Block a user