mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Reorganises internal state
`options` slice was huge and managed a mix of generation parameters and general app settings. It has been split up: - Generation parameters are now in `generationSlice`. - Postprocessing parameters are now in `postprocessingSlice` - UI related things are now in `uiSlice` There is probably more to be done, like `gallerySlice` perhaps should only manage internal gallery state, and not if the gallery is displayed. Full-slice selectors have been made for each slice. Other organisational tweaks.
This commit is contained in:
parent
511df2963b
commit
f80a64a0f4
52
invokeai/frontend/dist/assets/index-legacy-35973932.js
vendored
Normal file
52
invokeai/frontend/dist/assets/index-legacy-35973932.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
9
invokeai/frontend/dist/index.html
vendored
9
invokeai/frontend/dist/index.html
vendored
@ -7,8 +7,13 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
||||
<link rel="shortcut icon" type="icon" href="./assets/favicon.0d253ced.ico" />
|
||||
<<<<<<< HEAD
|
||||
<script type="module" crossorigin src="./assets/index.f3fa9388.js"></script>
|
||||
<link rel="stylesheet" href="./assets/index.1536494e.css">
|
||||
=======
|
||||
<script type="module" crossorigin src="./assets/index.5c5bc3f1.js"></script>
|
||||
<link rel="stylesheet" href="./assets/index.8badc8b4.css">
|
||||
>>>>>>> 64c0b743 (Reorganises internal state)
|
||||
<script type="module">try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.__vite_is_modern_browser=true;</script>
|
||||
<script type="module">!function(){if(window.__vite_is_modern_browser)return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("vite-legacy-polyfill"),n=document.createElement("script");n.src=e.src,n.onload=function(){System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))},document.body.appendChild(n)}();</script>
|
||||
</head>
|
||||
@ -18,6 +23,10 @@
|
||||
|
||||
<script nomodule>!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();</script>
|
||||
<script nomodule crossorigin id="vite-legacy-polyfill" src="./assets/polyfills-legacy-dde3a68a.js"></script>
|
||||
<<<<<<< HEAD
|
||||
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-4add591a.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
|
||||
=======
|
||||
<script nomodule crossorigin id="vite-legacy-entry" data-src="./assets/index-legacy-35973932.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
|
||||
>>>>>>> 64c0b743 (Reorganises internal state)
|
||||
</body>
|
||||
</html>
|
||||
|
@ -48,8 +48,8 @@
|
||||
"sendTo": "Send to",
|
||||
"sendToImg2Img": "Send to Image to Image",
|
||||
"sendToUnifiedCanvas": "Send To Unified Canvas",
|
||||
"copyImage": "Copy Image",
|
||||
"copyImageToLink": "Copy Image To Link",
|
||||
"copyImage": "Copy Image",
|
||||
"downloadImage": "Download Image",
|
||||
"openInViewer": "Open In Viewer",
|
||||
"closeViewer": "Close Viewer",
|
@ -2,13 +2,13 @@ import ProgressBar from 'features/system/components/ProgressBar';
|
||||
import SiteHeader from 'features/system/components/SiteHeader';
|
||||
import Console from 'features/system/components/Console';
|
||||
import { keepGUIAlive } from './utils';
|
||||
import InvokeTabs from 'features/tabs/components/InvokeTabs';
|
||||
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
||||
import ImageUploader from 'common/components/ImageUploader';
|
||||
|
||||
import useToastWatcher from 'features/system/hooks/useToastWatcher';
|
||||
|
||||
import FloatingOptionsPanelButtons from 'features/tabs/components/FloatingOptionsPanelButtons';
|
||||
import FloatingGalleryButton from 'features/tabs/components/FloatingGalleryButton';
|
||||
import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons';
|
||||
import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton';
|
||||
|
||||
keepGUIAlive();
|
||||
|
||||
@ -27,7 +27,7 @@ const App = () => {
|
||||
<Console />
|
||||
</div>
|
||||
</ImageUploader>
|
||||
<FloatingOptionsPanelButtons />
|
||||
<FloatingParametersPanelButtons />
|
||||
<FloatingGalleryButton />
|
||||
</div>
|
||||
);
|
||||
|
2
invokeai/frontend/src/app/invokeai.d.ts
vendored
2
invokeai/frontend/src/app/invokeai.d.ts
vendored
@ -12,7 +12,7 @@
|
||||
* 'gfpgan'.
|
||||
*/
|
||||
|
||||
import { InvokeTabName } from 'features/tabs/tabMap';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import { IRect } from 'konva/lib/types';
|
||||
|
||||
/**
|
||||
|
@ -1,32 +1,26 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
import { RootState } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { OptionsState } from 'features/options/store/optionsSlice';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
||||
import { initialCanvasImageSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||
|
||||
export const readinessSelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.options,
|
||||
(state: RootState) => state.system,
|
||||
generationSelector,
|
||||
systemSelector,
|
||||
initialCanvasImageSelector,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(
|
||||
options: OptionsState,
|
||||
system: SystemState,
|
||||
initialCanvasImage,
|
||||
activeTabName
|
||||
) => {
|
||||
(generation, system, initialCanvasImage, activeTabName) => {
|
||||
const {
|
||||
prompt,
|
||||
shouldGenerateVariations,
|
||||
seedWeights,
|
||||
initialImage,
|
||||
seed,
|
||||
} = options;
|
||||
} = generation;
|
||||
|
||||
const { isProcessing, isConnected } = system;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import { GalleryCategory } from 'features/gallery/store/gallerySlice';
|
||||
import { InvokeTabName } from 'features/tabs/tabMap';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
|
||||
/**
|
||||
|
@ -10,14 +10,13 @@ import {
|
||||
GalleryState,
|
||||
removeImage,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import { OptionsState } from 'features/options/store/optionsSlice';
|
||||
import {
|
||||
addLogEntry,
|
||||
generationRequested,
|
||||
modelChangeRequested,
|
||||
setIsProcessing,
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { InvokeTabName } from 'features/tabs/tabMap';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import type { RootState } from 'app/store';
|
||||
|
||||
@ -39,7 +38,8 @@ const makeSocketIOEmitters = (
|
||||
const state: RootState = getState();
|
||||
|
||||
const {
|
||||
options: optionsState,
|
||||
generation: generationState,
|
||||
postprocessing: postprocessingState,
|
||||
system: systemState,
|
||||
canvas: canvasState,
|
||||
} = state;
|
||||
@ -47,7 +47,8 @@ const makeSocketIOEmitters = (
|
||||
const frontendToBackendParametersConfig: FrontendToBackendParametersConfig =
|
||||
{
|
||||
generationMode,
|
||||
optionsState,
|
||||
generationState,
|
||||
postprocessingState,
|
||||
canvasState,
|
||||
systemState,
|
||||
};
|
||||
@ -90,8 +91,11 @@ const makeSocketIOEmitters = (
|
||||
},
|
||||
emitRunESRGAN: (imageToProcess: InvokeAI.Image) => {
|
||||
dispatch(setIsProcessing(true));
|
||||
const options: OptionsState = getState().options;
|
||||
const { upscalingLevel, upscalingStrength } = options;
|
||||
|
||||
const {
|
||||
postprocessing: { upscalingLevel, upscalingStrength },
|
||||
} = getState();
|
||||
|
||||
const esrganParameters = {
|
||||
upscale: [upscalingLevel, upscalingStrength],
|
||||
};
|
||||
@ -111,8 +115,10 @@ const makeSocketIOEmitters = (
|
||||
},
|
||||
emitRunFacetool: (imageToProcess: InvokeAI.Image) => {
|
||||
dispatch(setIsProcessing(true));
|
||||
const options: OptionsState = getState().options;
|
||||
const { facetoolType, facetoolStrength, codeformerFidelity } = options;
|
||||
|
||||
const {
|
||||
postprocessing: { facetoolType, facetoolStrength, codeformerFidelity },
|
||||
} = getState();
|
||||
|
||||
const facetoolParameters: Record<string, unknown> = {
|
||||
facetool_strength: facetoolStrength,
|
||||
|
@ -35,14 +35,14 @@ import {
|
||||
setInfillMethod,
|
||||
setInitialImage,
|
||||
setMaskPath,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import {
|
||||
requestImages,
|
||||
requestNewImages,
|
||||
requestSystemConfig,
|
||||
} from './actions';
|
||||
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
||||
import { tabMap } from 'features/tabs/tabMap';
|
||||
import { tabMap } from 'features/ui/store/tabMap';
|
||||
import type { RootState } from 'app/store';
|
||||
|
||||
/**
|
||||
@ -104,8 +104,9 @@ const makeSocketIOListeners = (
|
||||
*/
|
||||
onGenerationResult: (data: InvokeAI.ImageResultResponse) => {
|
||||
try {
|
||||
const state: RootState = getState();
|
||||
const { shouldLoopback, activeTab } = state.options;
|
||||
const state = getState();
|
||||
const { activeTab } = state.ui;
|
||||
const { shouldLoopback } = state.postprocessing;
|
||||
const { boundingBox: _, generationMode, ...rest } = data;
|
||||
|
||||
const newImage = {
|
||||
@ -327,7 +328,9 @@ const makeSocketIOListeners = (
|
||||
dispatch(removeImage(data));
|
||||
|
||||
// remove references to image in options
|
||||
const { initialImage, maskPath } = getState().options;
|
||||
const {
|
||||
generation: { initialImage, maskPath },
|
||||
} = getState();
|
||||
|
||||
if (
|
||||
initialImage === url ||
|
||||
|
@ -5,10 +5,13 @@ import storage from 'redux-persist/lib/storage'; // defaults to localStorage for
|
||||
|
||||
import { getPersistConfig } from 'redux-deep-persist';
|
||||
|
||||
import optionsReducer from 'features/options/store/optionsSlice';
|
||||
import generationReducer from 'features/parameters/store/generationSlice';
|
||||
import postprocessingReducer from 'features/parameters/store/postprocessingSlice';
|
||||
import galleryReducer from 'features/gallery/store/gallerySlice';
|
||||
import systemReducer from 'features/system/store/systemSlice';
|
||||
import canvasReducer from 'features/canvas/store/canvasSlice';
|
||||
import uiReducer from 'features/ui/store/uiSlice';
|
||||
import lightboxReducer from 'features/lightbox/store/lightboxSlice';
|
||||
|
||||
import { socketioMiddleware } from './socketio/middleware';
|
||||
|
||||
@ -58,10 +61,13 @@ const galleryBlacklist = [
|
||||
].map((blacklistItem) => `gallery.${blacklistItem}`);
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
options: optionsReducer,
|
||||
generation: generationReducer,
|
||||
postprocessing: postprocessingReducer,
|
||||
gallery: galleryReducer,
|
||||
system: systemReducer,
|
||||
canvas: canvasReducer,
|
||||
ui: uiReducer,
|
||||
lightbox: lightboxReducer,
|
||||
});
|
||||
|
||||
const rootPersistConfig = getPersistConfig({
|
||||
@ -89,8 +95,8 @@ export const store = configureStore({
|
||||
'canvas/setStageCoordinates',
|
||||
'canvas/setStageScale',
|
||||
'canvas/setIsDrawing',
|
||||
// 'canvas/setBoundingBoxCoordinates',
|
||||
// 'canvas/setBoundingBoxDimensions',
|
||||
'canvas/setBoundingBoxCoordinates',
|
||||
'canvas/setBoundingBoxDimensions',
|
||||
'canvas/setIsDrawing',
|
||||
'canvas/addPointToCurrentLine',
|
||||
],
|
||||
|
@ -7,23 +7,23 @@ import {
|
||||
} from '@chakra-ui/react';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import { useAppSelector } from 'app/storeHooks';
|
||||
import { RootState } from 'app/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { ReactElement } from 'react';
|
||||
import { Feature, useFeatureHelpInfo } from 'app/features';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
type GuideProps = {
|
||||
children: ReactElement;
|
||||
feature: Feature;
|
||||
};
|
||||
|
||||
const systemSelector = createSelector(
|
||||
(state: RootState) => state.system,
|
||||
const guidePopoverSelector = createSelector(
|
||||
systemSelector,
|
||||
(system: SystemState) => system.shouldDisplayGuides
|
||||
);
|
||||
|
||||
const GuidePopover = ({ children, feature }: GuideProps) => {
|
||||
const shouldDisplayGuides = useAppSelector(systemSelector);
|
||||
const shouldDisplayGuides = useAppSelector(guidePopoverSelector);
|
||||
const { text } = useFeatureHelpInfo(feature);
|
||||
|
||||
if (!shouldDisplayGuides) return null;
|
||||
|
@ -9,8 +9,8 @@ import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { FileRejection, useDropzone } from 'react-dropzone';
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { ImageUploaderTriggerContext } from 'app/contexts/ImageUploaderTriggerContext';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { tabDict } from 'features/tabs/components/InvokeTabs';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { tabDict } from 'features/ui/components/InvokeTabs';
|
||||
import ImageUploadOverlay from './ImageUploadOverlay';
|
||||
import { uploadImage } from 'features/gallery/store/thunks/uploadImage';
|
||||
import useImageUploader from 'common/hooks/useImageUploader';
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants';
|
||||
import { OptionsState } from 'features/options/store/optionsSlice';
|
||||
import { GenerationState } from 'features/parameters/store/generationSlice';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import { Dimensions } from 'features/canvas/store/canvasTypes';
|
||||
|
||||
import { stringToSeedWeightsArray } from './seedWeightPairs';
|
||||
import randomInt from './randomInt';
|
||||
import { InvokeTabName } from 'features/tabs/tabMap';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import {
|
||||
CanvasState,
|
||||
isCanvasMaskLine,
|
||||
@ -17,11 +17,13 @@ import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider';
|
||||
import type {
|
||||
UpscalingLevel,
|
||||
FacetoolType,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/postprocessingSlice';
|
||||
import { PostprocessingState } from 'features/parameters/store/postprocessingSlice';
|
||||
|
||||
export type FrontendToBackendParametersConfig = {
|
||||
generationMode: InvokeTabName;
|
||||
optionsState: OptionsState;
|
||||
generationState: GenerationState;
|
||||
postprocessingState: PostprocessingState;
|
||||
canvasState: CanvasState;
|
||||
systemState: SystemState;
|
||||
imageToProcessUrl?: string;
|
||||
@ -91,16 +93,31 @@ export const frontendToBackendParameters = (
|
||||
): BackendParameters => {
|
||||
const canvasBaseLayer = getCanvasBaseLayer();
|
||||
|
||||
const { generationMode, optionsState, canvasState, systemState } = config;
|
||||
const {
|
||||
generationMode,
|
||||
generationState,
|
||||
postprocessingState,
|
||||
canvasState,
|
||||
systemState,
|
||||
} = config;
|
||||
|
||||
const {
|
||||
cfgScale,
|
||||
codeformerFidelity,
|
||||
facetoolStrength,
|
||||
facetoolType,
|
||||
height,
|
||||
hiresFix,
|
||||
hiresStrength,
|
||||
shouldRunESRGAN,
|
||||
shouldRunFacetool,
|
||||
upscalingLevel,
|
||||
upscalingStrength,
|
||||
} = postprocessingState;
|
||||
|
||||
const {
|
||||
cfgScale,
|
||||
|
||||
height,
|
||||
|
||||
img2imgStrength,
|
||||
infillMethod,
|
||||
initialImage,
|
||||
@ -119,16 +136,14 @@ export const frontendToBackendParameters = (
|
||||
shouldFitToWidthHeight,
|
||||
shouldGenerateVariations,
|
||||
shouldRandomizeSeed,
|
||||
shouldRunESRGAN,
|
||||
shouldRunFacetool,
|
||||
|
||||
steps,
|
||||
threshold,
|
||||
tileSize,
|
||||
upscalingLevel,
|
||||
upscalingStrength,
|
||||
|
||||
variationAmount,
|
||||
width,
|
||||
} = optionsState;
|
||||
} = generationState;
|
||||
|
||||
const {
|
||||
shouldDisplayInProgressType,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Spinner } from '@chakra-ui/react';
|
||||
import { useLayoutEffect, useRef } from 'react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
resizeAndScaleCanvas,
|
||||
resizeCanvas,
|
||||
|
@ -3,7 +3,7 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { FaRedo } from 'react-icons/fa';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
|
||||
import _ from 'lodash';
|
||||
|
@ -6,7 +6,7 @@ import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { undo } from 'features/canvas/store/canvasSlice';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
clearMask,
|
||||
resetCanvasInteractionState,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import Konva from 'konva';
|
||||
import { KonvaEventObject } from 'konva/lib/Node';
|
||||
import _ from 'lodash';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import Konva from 'konva';
|
||||
import { Vector2d } from 'konva/lib/types';
|
||||
import _ from 'lodash';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import Konva from 'konva';
|
||||
import _ from 'lodash';
|
||||
import { MutableRefObject, useCallback } from 'react';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import { CanvasImage, CanvasState, isCanvasBaseImage } from './canvasTypes';
|
||||
|
||||
|
@ -1,28 +1,42 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
import { ButtonGroup, Link, useToast } from '@chakra-ui/react';
|
||||
import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { RootState } from 'app/store';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import { getPromptAndNegative } from 'common/util/getPromptAndNegative';
|
||||
import {
|
||||
setDoesCanvasNeedScaling,
|
||||
setInitialCanvasImage,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { GalleryState } from 'features/gallery/store/gallerySlice';
|
||||
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
||||
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
|
||||
import FaceRestoreSettings from 'features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreSettings';
|
||||
import UpscaleSettings from 'features/parameters/components/AdvancedParameters/Upscale/UpscaleSettings';
|
||||
import {
|
||||
OptionsState,
|
||||
setActiveTab,
|
||||
setAllParameters,
|
||||
setInitialImage,
|
||||
setIsLightBoxOpen,
|
||||
setNegativePrompt,
|
||||
setPrompt,
|
||||
setSeed,
|
||||
setShouldShowImageDetails,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
import DeleteImageModal from './DeleteImageModal';
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import UpscaleOptions from 'features/options/components/AdvancedOptions/Upscale/UpscaleOptions';
|
||||
import FaceRestoreOptions from 'features/options/components/AdvancedOptions/FaceRestore/FaceRestoreOptions';
|
||||
import {
|
||||
activeTabNameSelector,
|
||||
uiSelector,
|
||||
} from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
setActiveTab,
|
||||
setShouldShowImageDetails,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { ButtonGroup, Link, useToast } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
FaAsterisk,
|
||||
FaCode,
|
||||
@ -37,38 +51,34 @@ import {
|
||||
FaShareAlt,
|
||||
FaTrash,
|
||||
} from 'react-icons/fa';
|
||||
import {
|
||||
setDoesCanvasNeedScaling,
|
||||
setInitialCanvasImage,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { GalleryState } from 'features/gallery/store/gallerySlice';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getPromptAndNegative } from 'common/util/getPromptAndNegative';
|
||||
import { gallerySelector } from '../store/gallerySelectors';
|
||||
import DeleteImageModal from './DeleteImageModal';
|
||||
|
||||
const systemSelector = createSelector(
|
||||
const currentImageButtonsSelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.system,
|
||||
(state: RootState) => state.options,
|
||||
(state: RootState) => state.gallery,
|
||||
systemSelector,
|
||||
gallerySelector,
|
||||
postprocessingSelector,
|
||||
uiSelector,
|
||||
lightboxSelector,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(
|
||||
system: SystemState,
|
||||
options: OptionsState,
|
||||
gallery: GalleryState,
|
||||
postprocessing,
|
||||
ui,
|
||||
lightbox,
|
||||
activeTabName
|
||||
) => {
|
||||
const { isProcessing, isConnected, isGFPGANAvailable, isESRGANAvailable } =
|
||||
system;
|
||||
|
||||
const {
|
||||
upscalingLevel,
|
||||
facetoolStrength,
|
||||
shouldShowImageDetails,
|
||||
isLightBoxOpen,
|
||||
} = options;
|
||||
const { upscalingLevel, facetoolStrength } = postprocessing;
|
||||
|
||||
const { isLightboxOpen } = lightbox;
|
||||
|
||||
const { shouldShowImageDetails } = ui;
|
||||
|
||||
const { intermediateImage, currentImage } = gallery;
|
||||
|
||||
@ -83,7 +93,7 @@ const systemSelector = createSelector(
|
||||
currentImage,
|
||||
shouldShowImageDetails,
|
||||
activeTabName,
|
||||
isLightBoxOpen,
|
||||
isLightboxOpen,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -109,36 +119,20 @@ const CurrentImageButtons = () => {
|
||||
shouldDisableToolbarButtons,
|
||||
shouldShowImageDetails,
|
||||
currentImage,
|
||||
isLightBoxOpen,
|
||||
isLightboxOpen,
|
||||
activeTabName,
|
||||
} = useAppSelector(systemSelector);
|
||||
} = useAppSelector(currentImageButtonsSelector);
|
||||
|
||||
const toast = useToast();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleClickUseAsInitialImage = () => {
|
||||
if (!currentImage) return;
|
||||
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
||||
if (isLightboxOpen) dispatch(setIsLightboxOpen(false));
|
||||
dispatch(setInitialImage(currentImage));
|
||||
dispatch(setActiveTab('img2img'));
|
||||
};
|
||||
|
||||
const handleCopyImage = async () => {
|
||||
if (!currentImage) return;
|
||||
|
||||
const blob = await fetch(currentImage.url).then((res) => res.blob());
|
||||
const data = [new ClipboardItem({ [blob.type]: blob })];
|
||||
|
||||
await navigator.clipboard.write(data);
|
||||
|
||||
toast({
|
||||
title: t('toast:imageCopied'),
|
||||
status: 'success',
|
||||
duration: 2500,
|
||||
isClosable: true,
|
||||
});
|
||||
};
|
||||
|
||||
const handleCopyImageLink = () => {
|
||||
navigator.clipboard
|
||||
.writeText(
|
||||
@ -353,7 +347,7 @@ const CurrentImageButtons = () => {
|
||||
|
||||
const handleSendToCanvas = () => {
|
||||
if (!currentImage) return;
|
||||
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
||||
if (isLightboxOpen) dispatch(setIsLightboxOpen(false));
|
||||
|
||||
dispatch(setInitialCanvasImage(currentImage));
|
||||
dispatch(setDoesCanvasNeedScaling(true));
|
||||
@ -388,7 +382,7 @@ const CurrentImageButtons = () => {
|
||||
);
|
||||
|
||||
const handleLightBox = () => {
|
||||
dispatch(setIsLightBoxOpen(!isLightBoxOpen));
|
||||
dispatch(setIsLightboxOpen(!isLightboxOpen));
|
||||
};
|
||||
|
||||
return (
|
||||
@ -398,7 +392,7 @@ const CurrentImageButtons = () => {
|
||||
trigger="hover"
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
aria-label={`${t('options:sendTo')}...`}
|
||||
aria-label={`${t('parameters:sendTo')}...`}
|
||||
icon={<FaShareAlt />}
|
||||
/>
|
||||
}
|
||||
@ -409,34 +403,26 @@ const CurrentImageButtons = () => {
|
||||
onClick={handleClickUseAsInitialImage}
|
||||
leftIcon={<FaShare />}
|
||||
>
|
||||
{t('options:sendToImg2Img')}
|
||||
{t('parameters:sendToImg2Img')}
|
||||
</IAIButton>
|
||||
<IAIButton
|
||||
size={'sm'}
|
||||
onClick={handleSendToCanvas}
|
||||
leftIcon={<FaShare />}
|
||||
>
|
||||
{t('options:sendToUnifiedCanvas')}
|
||||
</IAIButton>
|
||||
|
||||
<IAIButton
|
||||
size={'sm'}
|
||||
onClick={handleCopyImage}
|
||||
leftIcon={<FaCopy />}
|
||||
>
|
||||
{t('options:copyImage')}
|
||||
{t('parameters:sendToUnifiedCanvas')}
|
||||
</IAIButton>
|
||||
<IAIButton
|
||||
size={'sm'}
|
||||
onClick={handleCopyImageLink}
|
||||
leftIcon={<FaCopy />}
|
||||
>
|
||||
{t('options:copyImageToLink')}
|
||||
{t('parameters:copyImageToLink')}
|
||||
</IAIButton>
|
||||
|
||||
<Link download={true} href={currentImage?.url}>
|
||||
<IAIButton leftIcon={<FaDownload />} size={'sm'} w="100%">
|
||||
{t('options:downloadImage')}
|
||||
{t('parameters:downloadImage')}
|
||||
</IAIButton>
|
||||
</Link>
|
||||
</div>
|
||||
@ -444,16 +430,16 @@ const CurrentImageButtons = () => {
|
||||
<IAIIconButton
|
||||
icon={<FaExpand />}
|
||||
tooltip={
|
||||
!isLightBoxOpen
|
||||
? `${t('options:openInViewer')} (Z)`
|
||||
: `${t('options:closeViewer')} (Z)`
|
||||
!isLightboxOpen
|
||||
? `${t('parameters:openInViewer')} (Z)`
|
||||
: `${t('parameters:closeViewer')} (Z)`
|
||||
}
|
||||
aria-label={
|
||||
!isLightBoxOpen
|
||||
? `${t('options:openInViewer')} (Z)`
|
||||
: `${t('options:closeViewer')} (Z)`
|
||||
!isLightboxOpen
|
||||
? `${t('parameters:openInViewer')} (Z)`
|
||||
: `${t('parameters:closeViewer')} (Z)`
|
||||
}
|
||||
data-selected={isLightBoxOpen}
|
||||
data-selected={isLightboxOpen}
|
||||
onClick={handleLightBox}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
@ -461,24 +447,24 @@ const CurrentImageButtons = () => {
|
||||
<ButtonGroup isAttached={true}>
|
||||
<IAIIconButton
|
||||
icon={<FaQuoteRight />}
|
||||
tooltip={`${t('options:usePrompt')} (P)`}
|
||||
aria-label={`${t('options:usePrompt')} (P)`}
|
||||
tooltip={`${t('parameters:usePrompt')} (P)`}
|
||||
aria-label={`${t('parameters:usePrompt')} (P)`}
|
||||
isDisabled={!currentImage?.metadata?.image?.prompt}
|
||||
onClick={handleClickUsePrompt}
|
||||
/>
|
||||
|
||||
<IAIIconButton
|
||||
icon={<FaSeedling />}
|
||||
tooltip={`${t('options:useSeed')} (S)`}
|
||||
aria-label={`${t('options:useSeed')} (S)`}
|
||||
tooltip={`${t('parameters:useSeed')} (S)`}
|
||||
aria-label={`${t('parameters:useSeed')} (S)`}
|
||||
isDisabled={!currentImage?.metadata?.image?.seed}
|
||||
onClick={handleClickUseSeed}
|
||||
/>
|
||||
|
||||
<IAIIconButton
|
||||
icon={<FaAsterisk />}
|
||||
tooltip={`${t('options:useAll')} (A)`}
|
||||
aria-label={`${t('options:useAll')} (A)`}
|
||||
tooltip={`${t('parameters:useAll')} (A)`}
|
||||
aria-label={`${t('parameters:useAll')} (A)`}
|
||||
isDisabled={
|
||||
!['txt2img', 'img2img'].includes(
|
||||
currentImage?.metadata?.image?.type
|
||||
@ -494,12 +480,12 @@ const CurrentImageButtons = () => {
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
icon={<FaGrinStars />}
|
||||
aria-label={t('options:restoreFaces')}
|
||||
aria-label={t('parameters:restoreFaces')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className="current-image-postprocessing-popover">
|
||||
<FaceRestoreOptions />
|
||||
<FaceRestoreSettings />
|
||||
<IAIButton
|
||||
isDisabled={
|
||||
!isGFPGANAvailable ||
|
||||
@ -509,7 +495,7 @@ const CurrentImageButtons = () => {
|
||||
}
|
||||
onClick={handleClickFixFaces}
|
||||
>
|
||||
{t('options:restoreFaces')}
|
||||
{t('parameters:restoreFaces')}
|
||||
</IAIButton>
|
||||
</div>
|
||||
</IAIPopover>
|
||||
@ -519,12 +505,12 @@ const CurrentImageButtons = () => {
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
icon={<FaExpandArrowsAlt />}
|
||||
aria-label={t('options:upscale')}
|
||||
aria-label={t('parameters:upscale')}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className="current-image-postprocessing-popover">
|
||||
<UpscaleOptions />
|
||||
<UpscaleSettings />
|
||||
<IAIButton
|
||||
isDisabled={
|
||||
!isESRGANAvailable ||
|
||||
@ -534,7 +520,7 @@ const CurrentImageButtons = () => {
|
||||
}
|
||||
onClick={handleClickUpscale}
|
||||
>
|
||||
{t('options:upscaleImage')}
|
||||
{t('parameters:upscaleImage')}
|
||||
</IAIButton>
|
||||
</div>
|
||||
</IAIPopover>
|
||||
@ -543,8 +529,8 @@ const CurrentImageButtons = () => {
|
||||
<ButtonGroup isAttached={true}>
|
||||
<IAIIconButton
|
||||
icon={<FaCode />}
|
||||
tooltip={`${t('options:info')} (I)`}
|
||||
aria-label={`${t('options:info')} (I)`}
|
||||
tooltip={`${t('parameters:info')} (I)`}
|
||||
aria-label={`${t('parameters:info')} (I)`}
|
||||
data-selected={shouldShowImageDetails}
|
||||
onClick={handleClickShowImageDetails}
|
||||
/>
|
||||
@ -553,8 +539,8 @@ const CurrentImageButtons = () => {
|
||||
<DeleteImageModal image={currentImage}>
|
||||
<IAIIconButton
|
||||
icon={<FaTrash />}
|
||||
tooltip={`${t('options:deleteImage')} (Del)`}
|
||||
aria-label={`${t('options:deleteImage')} (Del)`}
|
||||
tooltip={`${t('parameters:deleteImage')} (Del)`}
|
||||
aria-label={`${t('parameters:deleteImage')} (Del)`}
|
||||
isDisabled={!currentImage || !isConnected || isProcessing}
|
||||
style={{ backgroundColor: 'var(--btn-delete-image)' }}
|
||||
/>
|
||||
|
@ -1,23 +1,21 @@
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppSelector } from 'app/storeHooks';
|
||||
import CurrentImageButtons from './CurrentImageButtons';
|
||||
import { MdPhoto } from 'react-icons/md';
|
||||
import CurrentImagePreview from './CurrentImagePreview';
|
||||
import { GalleryState } from 'features/gallery/store/gallerySlice';
|
||||
import { OptionsState } from 'features/options/store/optionsSlice';
|
||||
import _ from 'lodash';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import {
|
||||
activeTabNameSelector,
|
||||
uiSelector,
|
||||
} from 'features/ui/store/uiSelectors';
|
||||
import { gallerySelector } from '../store/gallerySelectors';
|
||||
|
||||
export const currentImageDisplaySelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.gallery,
|
||||
(state: RootState) => state.options,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(gallery: GalleryState, options: OptionsState, activeTabName) => {
|
||||
[gallerySelector, uiSelector, activeTabNameSelector],
|
||||
(gallery: GalleryState, ui, activeTabName) => {
|
||||
const { currentImage, intermediateImage } = gallery;
|
||||
const { shouldShowImageDetails } = options;
|
||||
const { shouldShowImageDetails } = ui;
|
||||
|
||||
return {
|
||||
activeTabName,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { IconButton, Image } from '@chakra-ui/react';
|
||||
import { useState } from 'react';
|
||||
import { FaAngleLeft, FaAngleRight } from 'react-icons/fa';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import {
|
||||
GalleryCategory,
|
||||
@ -11,14 +10,15 @@ import {
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
import { OptionsState } from 'features/options/store/optionsSlice';
|
||||
import ImageMetadataViewer from './ImageMetaDataViewer/ImageMetadataViewer';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import { gallerySelector } from '../store/gallerySelectors';
|
||||
|
||||
export const imagesSelector = createSelector(
|
||||
[(state: RootState) => state.gallery, (state: RootState) => state.options],
|
||||
(gallery: GalleryState, options: OptionsState) => {
|
||||
[gallerySelector, uiSelector],
|
||||
(gallery: GalleryState, ui) => {
|
||||
const { currentCategory, currentImage, intermediateImage } = gallery;
|
||||
const { shouldShowImageDetails } = options;
|
||||
const { shouldShowImageDetails } = ui;
|
||||
|
||||
const tempImages =
|
||||
gallery.categories[
|
||||
|
@ -18,7 +18,6 @@ import { ChangeEvent, ReactElement, SyntheticEvent } from 'react';
|
||||
import { cloneElement, forwardRef, useRef } from 'react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { deleteImage } from 'app/socketio/actions';
|
||||
import { RootState } from 'app/store';
|
||||
import {
|
||||
setShouldConfirmOnDelete,
|
||||
SystemState,
|
||||
@ -26,9 +25,10 @@ import {
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import _ from 'lodash';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
const systemSelector = createSelector(
|
||||
(state: RootState) => state.system,
|
||||
const deleteImageModalSelector = createSelector(
|
||||
systemSelector,
|
||||
(system: SystemState) => {
|
||||
const { shouldConfirmOnDelete, isConnected, isProcessing } = system;
|
||||
return { shouldConfirmOnDelete, isConnected, isProcessing };
|
||||
@ -60,8 +60,9 @@ const DeleteImageModal = forwardRef(
|
||||
({ image, children }: DeleteImageModalProps, ref) => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const dispatch = useAppDispatch();
|
||||
const { shouldConfirmOnDelete, isConnected, isProcessing } =
|
||||
useAppSelector(systemSelector);
|
||||
const { shouldConfirmOnDelete, isConnected, isProcessing } = useAppSelector(
|
||||
deleteImageModalSelector
|
||||
);
|
||||
const cancelRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const handleClickDelete = (e: SyntheticEvent) => {
|
||||
|
@ -4,28 +4,28 @@ import {
|
||||
setCurrentImage,
|
||||
setShouldHoldGalleryOpen,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import { FaCheck, FaTrashAlt } from 'react-icons/fa';
|
||||
import DeleteImageModal from './DeleteImageModal';
|
||||
import { DragEvent, memo, useState } from 'react';
|
||||
import {
|
||||
setActiveTab,
|
||||
setAllImageToImageParameters,
|
||||
setAllParameters,
|
||||
setInitialImage,
|
||||
setIsLightBoxOpen,
|
||||
setNegativePrompt,
|
||||
setPrompt,
|
||||
setSeed,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { DragEvent, memo, useState } from 'react';
|
||||
import { FaCheck, FaTrashAlt } from 'react-icons/fa';
|
||||
import DeleteImageModal from './DeleteImageModal';
|
||||
|
||||
import * as ContextMenu from '@radix-ui/react-context-menu';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { getPromptAndNegative } from 'common/util/getPromptAndNegative';
|
||||
import {
|
||||
resizeAndScaleCanvas,
|
||||
setInitialCanvasImage,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { hoverableImageSelector } from 'features/gallery/store/gallerySliceSelectors';
|
||||
import { hoverableImageSelector } from 'features/gallery/store/gallerySelectors';
|
||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getPromptAndNegative } from 'common/util/getPromptAndNegative';
|
||||
|
||||
interface HoverableImageProps {
|
||||
image: InvokeAI.Image;
|
||||
@ -47,7 +47,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
galleryImageObjectFit,
|
||||
galleryImageMinimumWidth,
|
||||
mayDeleteImage,
|
||||
isLightBoxOpen,
|
||||
shouldUseSingleGalleryColumn,
|
||||
} = useAppSelector(hoverableImageSelector);
|
||||
const { image, isSelected } = props;
|
||||
@ -94,7 +93,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
};
|
||||
|
||||
const handleSendToImageToImage = () => {
|
||||
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
||||
dispatch(setInitialImage(image));
|
||||
if (activeTabName !== 'img2img') {
|
||||
dispatch(setActiveTab('img2img'));
|
||||
@ -108,8 +106,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
};
|
||||
|
||||
const handleSendToCanvas = () => {
|
||||
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
||||
|
||||
dispatch(setInitialCanvasImage(image));
|
||||
|
||||
dispatch(resizeAndScaleCanvas());
|
||||
@ -168,7 +164,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
};
|
||||
|
||||
const handleLightBox = () => {
|
||||
dispatch(setIsLightBoxOpen(true));
|
||||
dispatch(setCurrentImage(image));
|
||||
};
|
||||
|
||||
@ -212,7 +207,7 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
<div className="hoverable-image-delete-button">
|
||||
<DeleteImageModal image={image}>
|
||||
<IconButton
|
||||
aria-label={t('options:deleteImage')}
|
||||
aria-label={t('parameters:deleteImage')}
|
||||
icon={<FaTrashAlt />}
|
||||
size="xs"
|
||||
variant={'imageHoverIconButton'}
|
||||
@ -232,20 +227,20 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
}}
|
||||
>
|
||||
<ContextMenu.Item onClickCapture={handleLightBox}>
|
||||
{t('options:openInViewer')}
|
||||
{t('parameters:openInViewer')}
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item
|
||||
onClickCapture={handleUsePrompt}
|
||||
disabled={image?.metadata?.image?.prompt === undefined}
|
||||
>
|
||||
{t('options:usePrompt')}
|
||||
{t('parameters:usePrompt')}
|
||||
</ContextMenu.Item>
|
||||
|
||||
<ContextMenu.Item
|
||||
onClickCapture={handleUseSeed}
|
||||
disabled={image?.metadata?.image?.seed === undefined}
|
||||
>
|
||||
{t('options:useSeed')}
|
||||
{t('parameters:useSeed')}
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item
|
||||
onClickCapture={handleUseAllParameters}
|
||||
@ -253,23 +248,23 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
!['txt2img', 'img2img'].includes(image?.metadata?.image?.type)
|
||||
}
|
||||
>
|
||||
{t('options:useAll')}
|
||||
{t('parameters:useAll')}
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item
|
||||
onClickCapture={handleUseInitialImage}
|
||||
disabled={image?.metadata?.image?.type !== 'img2img'}
|
||||
>
|
||||
{t('options:useInitImg')}
|
||||
{t('parameters:useInitImg')}
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item onClickCapture={handleSendToImageToImage}>
|
||||
{t('options:sendToImg2Img')}
|
||||
{t('parameters:sendToImg2Img')}
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item onClickCapture={handleSendToCanvas}>
|
||||
{t('options:sendToUnifiedCanvas')}
|
||||
{t('parameters:sendToUnifiedCanvas')}
|
||||
</ContextMenu.Item>
|
||||
<ContextMenu.Item data-warning>
|
||||
<DeleteImageModal image={image}>
|
||||
<p>{t('options:deleteImage')}</p>
|
||||
<p>{t('parameters:deleteImage')}</p>
|
||||
</DeleteImageModal>
|
||||
</ContextMenu.Item>
|
||||
</ContextMenu.Content>
|
||||
|
@ -32,7 +32,7 @@ import { setShouldShowGallery } from 'features/gallery/store/gallerySlice';
|
||||
import { ButtonGroup } from '@chakra-ui/react';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
import { Direction } from 're-resizable/lib/resizer';
|
||||
import { imageGallerySelector } from 'features/gallery/store/gallerySliceSelectors';
|
||||
import { imageGallerySelector } from 'features/gallery/store/gallerySelectors';
|
||||
import { FaImage, FaUser, FaWrench } from 'react-icons/fa';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
@ -41,7 +41,7 @@ import IAICheckbox from 'common/components/IAICheckbox';
|
||||
import { setDoesCanvasNeedScaling } from 'features/canvas/store/canvasSlice';
|
||||
import _ from 'lodash';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import { InvokeTabName } from 'features/tabs/tabMap';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const GALLERY_SHOW_BUTTONS_MIN_WIDTH = 320;
|
||||
@ -81,13 +81,13 @@ export default function ImageGallery() {
|
||||
shouldAutoSwitchToNewImages,
|
||||
areMoreImagesAvailable,
|
||||
galleryWidth,
|
||||
isLightBoxOpen,
|
||||
isLightboxOpen,
|
||||
isStaging,
|
||||
shouldEnableResize,
|
||||
shouldUseSingleGalleryColumn,
|
||||
} = useAppSelector(imageGallerySelector);
|
||||
|
||||
const { galleryMinWidth, galleryMaxWidth } = isLightBoxOpen
|
||||
const { galleryMinWidth, galleryMaxWidth } = isLightboxOpen
|
||||
? {
|
||||
galleryMinWidth: LIGHTBOX_GALLERY_WIDTH,
|
||||
galleryMaxWidth: LIGHTBOX_GALLERY_WIDTH,
|
||||
|
@ -14,11 +14,7 @@ import { useAppDispatch } from 'app/storeHooks';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import {
|
||||
setCfgScale,
|
||||
setFacetoolStrength,
|
||||
setCodeformerFidelity,
|
||||
setFacetoolType,
|
||||
setHeight,
|
||||
setHiresFix,
|
||||
setImg2imgStrength,
|
||||
setMaskPath,
|
||||
setPrompt,
|
||||
@ -28,14 +24,20 @@ import {
|
||||
setSeedWeights,
|
||||
setShouldFitToWidthHeight,
|
||||
setSteps,
|
||||
setUpscalingLevel,
|
||||
setUpscalingStrength,
|
||||
setWidth,
|
||||
setInitialImage,
|
||||
setShouldShowImageDetails,
|
||||
setThreshold,
|
||||
setPerlin,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import {
|
||||
setFacetoolStrength,
|
||||
setCodeformerFidelity,
|
||||
setFacetoolType,
|
||||
setHiresFix,
|
||||
setUpscalingLevel,
|
||||
setUpscalingStrength,
|
||||
} from 'features/parameters/store/postprocessingSlice';
|
||||
import { setShouldShowImageDetails } from 'features/ui/store/uiSlice';
|
||||
import promptToString from 'common/util/promptToString';
|
||||
import { seedWeightsToString } from 'common/util/seedWeightPairs';
|
||||
import { FaCopy } from 'react-icons/fa';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/storeHooks';
|
||||
import { gallerySelector } from '../store/gallerySliceSelectors';
|
||||
import { gallerySelector } from '../store/gallerySelectors';
|
||||
|
||||
const selector = createSelector(gallerySelector, (gallery) => ({
|
||||
resultImages: gallery.categories.result.images,
|
||||
|
@ -1,20 +1,17 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState } from 'app/store';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { OptionsState } from 'features/options/store/optionsSlice';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { GalleryState } from './gallerySlice';
|
||||
import _ from 'lodash';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
export const gallerySelector = (state: RootState) => state.gallery;
|
||||
|
||||
export const imageGallerySelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.gallery,
|
||||
(state: RootState) => state.options,
|
||||
isStagingSelector,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(gallery: GalleryState, options: OptionsState, isStaging, activeTabName) => {
|
||||
[gallerySelector, lightboxSelector, isStagingSelector, activeTabNameSelector],
|
||||
(gallery: GalleryState, lightbox, isStaging, activeTabName) => {
|
||||
const {
|
||||
categories,
|
||||
currentCategory,
|
||||
@ -30,7 +27,7 @@ export const imageGallerySelector = createSelector(
|
||||
shouldUseSingleGalleryColumn,
|
||||
} = gallery;
|
||||
|
||||
const { isLightBoxOpen } = options;
|
||||
const { isLightboxOpen } = lightbox;
|
||||
|
||||
return {
|
||||
currentImageUuid,
|
||||
@ -50,10 +47,10 @@ export const imageGallerySelector = createSelector(
|
||||
categories[currentCategory].areMoreImagesAvailable,
|
||||
currentCategory,
|
||||
galleryWidth,
|
||||
isLightBoxOpen,
|
||||
isLightboxOpen,
|
||||
isStaging,
|
||||
shouldEnableResize:
|
||||
isLightBoxOpen ||
|
||||
isLightboxOpen ||
|
||||
(activeTabName === 'unifiedCanvas' && shouldPinGallery)
|
||||
? false
|
||||
: true,
|
||||
@ -68,25 +65,15 @@ export const imageGallerySelector = createSelector(
|
||||
);
|
||||
|
||||
export const hoverableImageSelector = createSelector(
|
||||
[
|
||||
(state: RootState) => state.options,
|
||||
(state: RootState) => state.gallery,
|
||||
(state: RootState) => state.system,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(
|
||||
options: OptionsState,
|
||||
gallery: GalleryState,
|
||||
system: SystemState,
|
||||
activeTabName
|
||||
) => {
|
||||
[gallerySelector, systemSelector, lightboxSelector, activeTabNameSelector],
|
||||
(gallery: GalleryState, system, lightbox, activeTabName) => {
|
||||
return {
|
||||
mayDeleteImage: system.isConnected && !system.isProcessing,
|
||||
galleryImageObjectFit: gallery.galleryImageObjectFit,
|
||||
galleryImageMinimumWidth: gallery.galleryImageMinimumWidth,
|
||||
shouldUseSingleGalleryColumn: gallery.shouldUseSingleGalleryColumn,
|
||||
activeTabName,
|
||||
isLightBoxOpen: options.isLightBoxOpen,
|
||||
isLightboxOpen: lightbox.isLightboxOpen,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -95,5 +82,3 @@ export const hoverableImageSelector = createSelector(
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export const gallerySelector = (state: RootState) => state.gallery;
|
@ -3,7 +3,7 @@ import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import _, { clamp } from 'lodash';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { IRect } from 'konva/lib/types';
|
||||
import { InvokeTabName } from 'features/tabs/tabMap';
|
||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||
|
||||
export type GalleryCategory = 'user' | 'result';
|
||||
|
||||
@ -241,6 +241,7 @@ export const gallerySlice = createSlice({
|
||||
setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowGallery = action.payload;
|
||||
},
|
||||
|
||||
setGalleryScrollPosition: (state, action: PayloadAction<number>) => {
|
||||
state.galleryScrollPosition = action.payload;
|
||||
},
|
||||
|
@ -2,9 +2,9 @@ import { AnyAction, ThunkAction } from '@reduxjs/toolkit';
|
||||
import { RootState } from 'app/store';
|
||||
import * as InvokeAI from 'app/invokeai';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||
import { setInitialImage } from 'features/options/store/optionsSlice';
|
||||
import { setInitialImage } from 'features/parameters/store/generationSlice';
|
||||
import { addImage } from '../gallerySlice';
|
||||
|
||||
type UploadImageConfig = {
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
import ImageGallery from 'features/gallery/components/ImageGallery';
|
||||
import ImageMetadataViewer from 'features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer';
|
||||
import { setIsLightBoxOpen } from 'features/options/store/optionsSlice';
|
||||
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
|
||||
import React, { useState } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { BiExit } from 'react-icons/bi';
|
||||
@ -20,7 +20,7 @@ import ReactPanZoom from './ReactPanZoom';
|
||||
export default function Lightbox() {
|
||||
const dispatch = useAppDispatch();
|
||||
const isLightBoxOpen = useAppSelector(
|
||||
(state: RootState) => state.options.isLightBoxOpen
|
||||
(state: RootState) => state.lightbox.isLightboxOpen
|
||||
);
|
||||
|
||||
const {
|
||||
@ -52,7 +52,7 @@ export default function Lightbox() {
|
||||
useHotkeys(
|
||||
'Esc',
|
||||
() => {
|
||||
if (isLightBoxOpen) dispatch(setIsLightBoxOpen(false));
|
||||
if (isLightBoxOpen) dispatch(setIsLightboxOpen(false));
|
||||
},
|
||||
[isLightBoxOpen]
|
||||
);
|
||||
@ -64,7 +64,7 @@ export default function Lightbox() {
|
||||
aria-label="Exit Viewer"
|
||||
className="lightbox-close-btn"
|
||||
onClick={() => {
|
||||
dispatch(setIsLightBoxOpen(false));
|
||||
dispatch(setIsLightboxOpen(false));
|
||||
}}
|
||||
fontSize={20}
|
||||
/>
|
||||
|
@ -0,0 +1,13 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { RootState } from 'app/store';
|
||||
import _ from 'lodash';
|
||||
|
||||
export const lightboxSelector = createSelector(
|
||||
(state: RootState) => state.lightbox,
|
||||
(lightbox) => lightbox,
|
||||
{
|
||||
memoizeOptions: {
|
||||
equalityCheck: _.isEqual,
|
||||
},
|
||||
}
|
||||
);
|
@ -0,0 +1,26 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
export interface LightboxState {
|
||||
isLightboxOpen: boolean;
|
||||
}
|
||||
|
||||
const initialLightboxState: LightboxState = {
|
||||
isLightboxOpen: false,
|
||||
};
|
||||
|
||||
const initialState: LightboxState = initialLightboxState;
|
||||
|
||||
export const lightboxSlice = createSlice({
|
||||
name: 'lightbox',
|
||||
initialState,
|
||||
reducers: {
|
||||
setIsLightboxOpen: (state, action: PayloadAction<boolean>) => {
|
||||
state.isLightboxOpen = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setIsLightboxOpen } = lightboxSlice.actions;
|
||||
|
||||
export default lightboxSlice.reducer;
|
@ -1,12 +0,0 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import SeamlessOptions from './SeamlessOptions';
|
||||
|
||||
const ImageToImageOutputOptions = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<SeamlessOptions />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageToImageOutputOptions;
|
@ -1,14 +0,0 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import HiresOptions from './HiresOptions';
|
||||
import SeamlessOptions from './SeamlessOptions';
|
||||
|
||||
const OutputOptions = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<SeamlessOptions />
|
||||
<HiresOptions />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default OutputOptions;
|
@ -1,24 +0,0 @@
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAICheckbox from 'common/components/IAICheckbox';
|
||||
import { setShowAdvancedOptions } from 'features/options/store/optionsSlice';
|
||||
|
||||
export default function MainAdvancedOptionsCheckbox() {
|
||||
const showAdvancedOptions = useAppSelector(
|
||||
(state: RootState) => state.options.showAdvancedOptions
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleShowAdvancedOptions = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch(setShowAdvancedOptions(e.target.checked));
|
||||
|
||||
return (
|
||||
<IAICheckbox
|
||||
label="Advanced Options"
|
||||
styleClass="advanced-options-checkbox"
|
||||
onChange={handleShowAdvancedOptions}
|
||||
isChecked={showAdvancedOptions}
|
||||
/>
|
||||
);
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import _ from 'lodash';
|
||||
import { RootState } from 'app/store';
|
||||
import { tabMap } from 'features/tabs/tabMap';
|
||||
import { OptionsState } from './optionsSlice';
|
||||
|
||||
export const activeTabNameSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(options: OptionsState) => tabMap[options.activeTab],
|
||||
{
|
||||
memoizeOptions: {
|
||||
equalityCheck: _.isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export const mayGenerateMultipleImagesSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(options: OptionsState) => {
|
||||
const { shouldRandomizeSeed, shouldGenerateVariations } = options;
|
||||
|
||||
return shouldRandomizeSeed || shouldGenerateVariations;
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: _.isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export const optionsSelector = (state: RootState): OptionsState =>
|
||||
state.options;
|
@ -1,12 +1,12 @@
|
||||
@use '../../../../styles/Mixins/' as *;
|
||||
|
||||
.advanced-settings {
|
||||
.advanced-parameters {
|
||||
padding-top: 0.5rem;
|
||||
display: grid;
|
||||
row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.advanced-settings-item {
|
||||
.advanced-parameters-item {
|
||||
display: grid;
|
||||
max-width: $options-bar-max-width;
|
||||
border: none;
|
||||
@ -20,7 +20,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.advanced-settings-panel {
|
||||
.advanced-parameters-panel {
|
||||
background-color: var(--tab-panel-bg);
|
||||
border-radius: 0 0 0.4rem 0.4rem;
|
||||
padding: 1rem;
|
||||
@ -39,7 +39,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.advanced-settings-header {
|
||||
.advanced-parameters-header {
|
||||
border-radius: 0.4rem;
|
||||
font-weight: bold;
|
||||
|
@ -21,8 +21,8 @@ export default function InvokeAccordionItem(props: InvokeAccordionItemProps) {
|
||||
const { header, feature, content, additionalHeaderComponents } = props;
|
||||
|
||||
return (
|
||||
<AccordionItem className="advanced-settings-item">
|
||||
<AccordionButton className="advanced-settings-header">
|
||||
<AccordionItem className="advanced-parameters-item">
|
||||
<AccordionButton className="advanced-parameters-header">
|
||||
<Flex width={'100%'} gap={'0.5rem'} align={'center'}>
|
||||
<Box flexGrow={1} textAlign={'left'}>
|
||||
{header}
|
||||
@ -32,7 +32,7 @@ export default function InvokeAccordionItem(props: InvokeAccordionItemProps) {
|
||||
<AccordionIcon />
|
||||
</Flex>
|
||||
</AccordionButton>
|
||||
<AccordionPanel className="advanced-settings-panel">
|
||||
<AccordionPanel className="advanced-parameters-panel">
|
||||
{content}
|
||||
</AccordionPanel>
|
||||
</AccordionItem>
|
@ -69,7 +69,7 @@ const BoundingBoxSettings = () => {
|
||||
return (
|
||||
<Flex direction="column" gap="1rem">
|
||||
<IAISlider
|
||||
label={t('options:width')}
|
||||
label={t('parameters:width')}
|
||||
min={64}
|
||||
max={1024}
|
||||
step={64}
|
||||
@ -83,7 +83,7 @@ const BoundingBoxSettings = () => {
|
||||
handleReset={handleResetWidth}
|
||||
/>
|
||||
<IAISlider
|
||||
label={t('options:height')}
|
||||
label={t('parameters:height')}
|
||||
min={64}
|
||||
max={1024}
|
||||
step={64}
|
||||
@ -106,7 +106,7 @@ export const BoundingBoxSettingsHeader = () => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Box flex="1" textAlign="left">
|
||||
{t('options:boundingBoxHeader')}
|
||||
{t('parameters:boundingBoxHeader')}
|
||||
</Box>
|
||||
);
|
||||
};
|
@ -12,20 +12,20 @@ import {
|
||||
BoundingBoxScale,
|
||||
BOUNDING_BOX_SCALES_DICT,
|
||||
} from 'features/canvas/store/canvasTypes';
|
||||
import { optionsSelector } from 'features/options/store/optionsSelectors';
|
||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||
import {
|
||||
setInfillMethod,
|
||||
setTileSize,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import _ from 'lodash';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
[optionsSelector, systemSelector, canvasSelector],
|
||||
(options, system, canvas) => {
|
||||
const { tileSize, infillMethod } = options;
|
||||
[generationSelector, systemSelector, canvasSelector],
|
||||
(parameters, system, canvas) => {
|
||||
const { tileSize, infillMethod } = parameters;
|
||||
|
||||
const { infill_methods: availableInfillMethods } = system;
|
||||
|
||||
@ -50,7 +50,7 @@ const selector = createSelector(
|
||||
}
|
||||
);
|
||||
|
||||
const InfillAndScalingOptions = () => {
|
||||
const InfillAndScalingSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
tileSize,
|
||||
@ -108,7 +108,7 @@ const InfillAndScalingOptions = () => {
|
||||
return (
|
||||
<Flex direction="column" gap="1rem">
|
||||
<IAISelect
|
||||
label={t('options:scaleBeforeProcessing')}
|
||||
label={t('parameters:scaleBeforeProcessing')}
|
||||
validValues={BOUNDING_BOX_SCALES_DICT}
|
||||
value={boundingBoxScale}
|
||||
onChange={handleChangeBoundingBoxScaleMethod}
|
||||
@ -117,7 +117,7 @@ const InfillAndScalingOptions = () => {
|
||||
isInputDisabled={!isManual}
|
||||
isResetDisabled={!isManual}
|
||||
isSliderDisabled={!isManual}
|
||||
label={t('options:scaledWidth')}
|
||||
label={t('parameters:scaledWidth')}
|
||||
min={64}
|
||||
max={1024}
|
||||
step={64}
|
||||
@ -134,7 +134,7 @@ const InfillAndScalingOptions = () => {
|
||||
isInputDisabled={!isManual}
|
||||
isResetDisabled={!isManual}
|
||||
isSliderDisabled={!isManual}
|
||||
label={t('options:scaledHeight')}
|
||||
label={t('parameters:scaledHeight')}
|
||||
min={64}
|
||||
max={1024}
|
||||
step={64}
|
||||
@ -148,7 +148,7 @@ const InfillAndScalingOptions = () => {
|
||||
handleReset={handleResetScaledHeight}
|
||||
/>
|
||||
<IAISelect
|
||||
label={t('options:infillMethod')}
|
||||
label={t('parameters:infillMethod')}
|
||||
value={infillMethod}
|
||||
validValues={availableInfillMethods}
|
||||
onChange={(e) => dispatch(setInfillMethod(e.target.value))}
|
||||
@ -158,7 +158,7 @@ const InfillAndScalingOptions = () => {
|
||||
isResetDisabled={infillMethod !== 'tile'}
|
||||
isSliderDisabled={infillMethod !== 'tile'}
|
||||
sliderMarkRightOffset={-4}
|
||||
label={t('options:tileSize')}
|
||||
label={t('parameters:tileSize')}
|
||||
min={16}
|
||||
max={64}
|
||||
sliderNumberInputProps={{ max: 256 }}
|
||||
@ -177,4 +177,4 @@ const InfillAndScalingOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default InfillAndScalingOptions;
|
||||
export default InfillAndScalingSettings;
|
@ -1,19 +1,20 @@
|
||||
import type { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setSeamBlur } from 'features/options/store/optionsSlice';
|
||||
import React from 'react';
|
||||
import { setSeamBlur } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SeamBlur() {
|
||||
const dispatch = useAppDispatch();
|
||||
const seamBlur = useAppSelector((state: RootState) => state.options.seamBlur);
|
||||
const seamBlur = useAppSelector(
|
||||
(state: RootState) => state.generation.seamBlur
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
sliderMarkRightOffset={-4}
|
||||
label={t('options:seamBlur')}
|
||||
label={t('parameters:seamBlur')}
|
||||
min={0}
|
||||
max={64}
|
||||
sliderNumberInputProps={{ max: 512 }}
|
@ -4,7 +4,7 @@ import SeamSize from './SeamSize';
|
||||
import SeamSteps from './SeamSteps';
|
||||
import SeamStrength from './SeamStrength';
|
||||
|
||||
const SeamCorrectionOptions = () => {
|
||||
const SeamCorrectionSettings = () => {
|
||||
return (
|
||||
<Flex direction="column" gap="1rem">
|
||||
<SeamSize />
|
||||
@ -15,4 +15,4 @@ const SeamCorrectionOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SeamCorrectionOptions;
|
||||
export default SeamCorrectionSettings;
|
@ -1,7 +1,7 @@
|
||||
import type { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setSeamSize } from 'features/options/store/optionsSlice';
|
||||
import { setSeamSize } from 'features/parameters/store/generationSlice';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -9,12 +9,12 @@ export default function SeamSize() {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const seamSize = useAppSelector((state: RootState) => state.options.seamSize);
|
||||
const seamSize = useAppSelector((state: RootState) => state.generation.seamSize);
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
sliderMarkRightOffset={-6}
|
||||
label={t('options:seamSize')}
|
||||
label={t('parameters:seamSize')}
|
||||
min={1}
|
||||
max={256}
|
||||
sliderNumberInputProps={{ max: 512 }}
|
@ -1,21 +1,21 @@
|
||||
import type { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setSeamSteps } from 'features/options/store/optionsSlice';
|
||||
import { setSeamSteps } from 'features/parameters/store/generationSlice';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SeamSteps() {
|
||||
const { t } = useTranslation();
|
||||
const seamSteps = useAppSelector(
|
||||
(state: RootState) => state.options.seamSteps
|
||||
(state: RootState) => state.generation.seamSteps
|
||||
);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
sliderMarkRightOffset={-4}
|
||||
label={t('options:seamSteps')}
|
||||
label={t('parameters:seamSteps')}
|
||||
min={1}
|
||||
max={100}
|
||||
sliderNumberInputProps={{ max: 999 }}
|
@ -1,7 +1,7 @@
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setSeamStrength } from 'features/options/store/optionsSlice';
|
||||
import { setSeamStrength } from 'features/parameters/store/generationSlice';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -9,13 +9,13 @@ export default function SeamStrength() {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const seamStrength = useAppSelector(
|
||||
(state: RootState) => state.options.seamStrength
|
||||
(state: RootState) => state.generation.seamStrength
|
||||
);
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
sliderMarkRightOffset={-7}
|
||||
label={t('options:seamStrength')}
|
||||
label={t('parameters:seamStrength')}
|
||||
min={0.01}
|
||||
max={0.99}
|
||||
step={0.01}
|
@ -1,46 +1,36 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
|
||||
import { FacetoolType } from 'features/parameters/store/postprocessingSlice';
|
||||
|
||||
import {
|
||||
FacetoolType,
|
||||
OptionsState,
|
||||
setCodeformerFidelity,
|
||||
setFacetoolStrength,
|
||||
setFacetoolType,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/postprocessingSlice';
|
||||
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { isEqual } from 'lodash';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import IAISelect from 'common/components/IAISelect';
|
||||
import { FACETOOL_TYPES } from 'app/constants';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
const optionsSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(options: OptionsState) => {
|
||||
[postprocessingSelector, systemSelector],
|
||||
(
|
||||
{ facetoolStrength, facetoolType, codeformerFidelity },
|
||||
{ isGFPGANAvailable }
|
||||
) => {
|
||||
return {
|
||||
facetoolStrength: options.facetoolStrength,
|
||||
facetoolType: options.facetoolType,
|
||||
codeformerFidelity: options.codeformerFidelity,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const systemSelector = createSelector(
|
||||
(state: RootState) => state.system,
|
||||
(system: SystemState) => {
|
||||
return {
|
||||
isGFPGANAvailable: system.isGFPGANAvailable,
|
||||
facetoolStrength,
|
||||
facetoolType,
|
||||
codeformerFidelity,
|
||||
isGFPGANAvailable,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -53,11 +43,14 @@ const systemSelector = createSelector(
|
||||
/**
|
||||
* Displays face-fixing/GFPGAN options (strength).
|
||||
*/
|
||||
const FaceRestoreOptions = () => {
|
||||
const FaceRestoreSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { facetoolStrength, facetoolType, codeformerFidelity } =
|
||||
useAppSelector(optionsSelector);
|
||||
const { isGFPGANAvailable } = useAppSelector(systemSelector);
|
||||
const {
|
||||
facetoolStrength,
|
||||
facetoolType,
|
||||
codeformerFidelity,
|
||||
isGFPGANAvailable,
|
||||
} = useAppSelector(optionsSelector);
|
||||
|
||||
const handleChangeStrength = (v: number) => dispatch(setFacetoolStrength(v));
|
||||
|
||||
@ -72,14 +65,14 @@ const FaceRestoreOptions = () => {
|
||||
return (
|
||||
<Flex direction={'column'} gap={2}>
|
||||
<IAISelect
|
||||
label={t('options:type')}
|
||||
label={t('parameters:type')}
|
||||
validValues={FACETOOL_TYPES.concat()}
|
||||
value={facetoolType}
|
||||
onChange={handleChangeFacetoolType}
|
||||
/>
|
||||
<IAINumberInput
|
||||
isDisabled={!isGFPGANAvailable}
|
||||
label={t('options:strength')}
|
||||
label={t('parameters:strength')}
|
||||
step={0.05}
|
||||
min={0}
|
||||
max={1}
|
||||
@ -91,7 +84,7 @@ const FaceRestoreOptions = () => {
|
||||
{facetoolType === 'codeformer' && (
|
||||
<IAINumberInput
|
||||
isDisabled={!isGFPGANAvailable}
|
||||
label={t('options:codeformerFidelity')}
|
||||
label={t('parameters:codeformerFidelity')}
|
||||
step={0.05}
|
||||
min={0}
|
||||
max={1}
|
||||
@ -105,4 +98,4 @@ const FaceRestoreOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default FaceRestoreOptions;
|
||||
export default FaceRestoreSettings;
|
@ -2,7 +2,7 @@ import { ChangeEvent } from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldRunFacetool } from 'features/options/store/optionsSlice';
|
||||
import { setShouldRunFacetool } from 'features/parameters/store/postprocessingSlice';
|
||||
|
||||
export default function FaceRestoreToggle() {
|
||||
const isGFPGANAvailable = useAppSelector(
|
||||
@ -10,7 +10,7 @@ export default function FaceRestoreToggle() {
|
||||
);
|
||||
|
||||
const shouldRunFacetool = useAppSelector(
|
||||
(state: RootState) => state.options.shouldRunFacetool
|
||||
(state: RootState) => state.postprocessing.shouldRunFacetool
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
@ -2,14 +2,14 @@ import React, { ChangeEvent } from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldFitToWidthHeight } from 'features/options/store/optionsSlice';
|
||||
import { setShouldFitToWidthHeight } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function ImageFit() {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const shouldFitToWidthHeight = useAppSelector(
|
||||
(state: RootState) => state.options.shouldFitToWidthHeight
|
||||
(state: RootState) => state.generation.shouldFitToWidthHeight
|
||||
);
|
||||
|
||||
const handleChangeFit = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
@ -19,7 +19,7 @@ export default function ImageFit() {
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label={t('options:imageFit')}
|
||||
label={t('parameters:imageFit')}
|
||||
isChecked={shouldFitToWidthHeight}
|
||||
onChange={handleChangeFit}
|
||||
/>
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setImg2imgStrength } from 'features/options/store/optionsSlice';
|
||||
import { setImg2imgStrength } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface ImageToImageStrengthProps {
|
||||
@ -12,9 +12,9 @@ interface ImageToImageStrengthProps {
|
||||
|
||||
export default function ImageToImageStrength(props: ImageToImageStrengthProps) {
|
||||
const { t } = useTranslation();
|
||||
const { label = `${t('options:strength')}`, styleClass } = props;
|
||||
const { label = `${t('parameters:strength')}`, styleClass } = props;
|
||||
const img2imgStrength = useAppSelector(
|
||||
(state: RootState) => state.options.img2imgStrength
|
||||
(state: RootState) => state.generation.img2imgStrength
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
@ -1,20 +1,30 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import type { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
|
||||
import {
|
||||
setHiresFix,
|
||||
setHiresStrength,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/postprocessingSlice';
|
||||
import { isEqual } from 'lodash';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
|
||||
function HighResStrength() {
|
||||
const hiresFix = useAppSelector((state: RootState) => state.options.hiresFix);
|
||||
const hiresStrength = useAppSelector(
|
||||
(state: RootState) => state.options.hiresStrength
|
||||
);
|
||||
const hiresStrengthSelector = createSelector(
|
||||
[postprocessingSelector],
|
||||
({ hiresFix, hiresStrength }) => ({ hiresFix, hiresStrength }),
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const HiresStrength = () => {
|
||||
const { hiresFix, hiresStrength } = useAppSelector(hiresStrengthSelector);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@ -30,7 +40,7 @@ function HighResStrength() {
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
label={t('options:hiresStrength')}
|
||||
label={t('parameters:hiresStrength')}
|
||||
step={0.01}
|
||||
min={0.01}
|
||||
max={0.99}
|
||||
@ -47,15 +57,17 @@ function HighResStrength() {
|
||||
isResetDisabled={!hiresFix}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hires Fix Toggle
|
||||
*/
|
||||
const HiresOptions = () => {
|
||||
const HiresSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const hiresFix = useAppSelector((state: RootState) => state.options.hiresFix);
|
||||
const hiresFix = useAppSelector(
|
||||
(state: RootState) => state.postprocessing.hiresFix
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -65,14 +77,14 @@ const HiresOptions = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<IAISwitch
|
||||
label={t('options:hiresOptim')}
|
||||
label={t('parameters:hiresOptim')}
|
||||
fontSize={'md'}
|
||||
isChecked={hiresFix}
|
||||
onChange={handleChangeHiresFix}
|
||||
/>
|
||||
<HighResStrength />
|
||||
<HiresStrength />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default HiresOptions;
|
||||
export default HiresSettings;
|
@ -0,0 +1,12 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import SeamlessSettings from './SeamlessSettings';
|
||||
|
||||
const ImageToImageOutputSettings = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<SeamlessSettings />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImageToImageOutputSettings;
|
@ -0,0 +1,14 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import HiresSettings from './HiresSettings';
|
||||
import SeamlessSettings from './SeamlessSettings';
|
||||
|
||||
const OutputSettings = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<SeamlessSettings />
|
||||
<HiresSettings />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default OutputSettings;
|
@ -3,16 +3,16 @@ import { ChangeEvent } from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setSeamless } from 'features/options/store/optionsSlice';
|
||||
import { setSeamless } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
/**
|
||||
* Seamless tiling toggle
|
||||
*/
|
||||
const SeamlessOptions = () => {
|
||||
const SeamlessSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const seamless = useAppSelector((state: RootState) => state.options.seamless);
|
||||
const seamless = useAppSelector((state: RootState) => state.generation.seamless);
|
||||
|
||||
const handleChangeSeamless = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch(setSeamless(e.target.checked));
|
||||
@ -22,7 +22,7 @@ const SeamlessOptions = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<IAISwitch
|
||||
label={t('options:seamlessTiling')}
|
||||
label={t('parameters:seamlessTiling')}
|
||||
fontSize={'md'}
|
||||
isChecked={seamless}
|
||||
onChange={handleChangeSeamless}
|
||||
@ -31,4 +31,4 @@ const SeamlessOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SeamlessOptions;
|
||||
export default SeamlessSettings;
|
@ -2,19 +2,19 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import { setPerlin } from 'features/options/store/optionsSlice';
|
||||
import { setPerlin } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function Perlin() {
|
||||
const dispatch = useAppDispatch();
|
||||
const perlin = useAppSelector((state: RootState) => state.options.perlin);
|
||||
const perlin = useAppSelector((state: RootState) => state.generation.perlin);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangePerlin = (v: number) => dispatch(setPerlin(v));
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:perlinNoise')}
|
||||
label={t('parameters:perlinNoise')}
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.05}
|
@ -4,7 +4,7 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldRandomizeSeed } from 'features/options/store/optionsSlice';
|
||||
import { setShouldRandomizeSeed } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function RandomizeSeed() {
|
||||
@ -12,7 +12,7 @@ export default function RandomizeSeed() {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const shouldRandomizeSeed = useAppSelector(
|
||||
(state: RootState) => state.options.shouldRandomizeSeed
|
||||
(state: RootState) => state.generation.shouldRandomizeSeed
|
||||
);
|
||||
|
||||
const handleChangeShouldRandomizeSeed = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
@ -20,7 +20,7 @@ export default function RandomizeSeed() {
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label={t('options:randomizeSeed')}
|
||||
label={t('parameters:randomizeSeed')}
|
||||
isChecked={shouldRandomizeSeed}
|
||||
onChange={handleChangeShouldRandomizeSeed}
|
||||
/>
|
@ -3,16 +3,16 @@ import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import { setSeed } from 'features/options/store/optionsSlice';
|
||||
import { setSeed } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function Seed() {
|
||||
const seed = useAppSelector((state: RootState) => state.options.seed);
|
||||
const seed = useAppSelector((state: RootState) => state.generation.seed);
|
||||
const shouldRandomizeSeed = useAppSelector(
|
||||
(state: RootState) => state.options.shouldRandomizeSeed
|
||||
(state: RootState) => state.generation.shouldRandomizeSeed
|
||||
);
|
||||
const shouldGenerateVariations = useAppSelector(
|
||||
(state: RootState) => state.options.shouldGenerateVariations
|
||||
(state: RootState) => state.generation.shouldGenerateVariations
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
@ -23,7 +23,7 @@ export default function Seed() {
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:seed')}
|
||||
label={t('parameters:seed')}
|
||||
step={1}
|
||||
precision={0}
|
||||
flexGrow={1}
|
@ -8,7 +8,7 @@ import Perlin from './Perlin';
|
||||
/**
|
||||
* Seed & variation options. Includes iteration, seed, seed randomization, variation options.
|
||||
*/
|
||||
const SeedOptions = () => {
|
||||
const SeedSettings = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<RandomizeSeed />
|
||||
@ -26,4 +26,4 @@ const SeedOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default SeedOptions;
|
||||
export default SeedSettings;
|
@ -4,13 +4,13 @@ import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import randomInt from 'common/util/randomInt';
|
||||
import { setSeed } from 'features/options/store/optionsSlice';
|
||||
import { setSeed } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function ShuffleSeed() {
|
||||
const dispatch = useAppDispatch();
|
||||
const shouldRandomizeSeed = useAppSelector(
|
||||
(state: RootState) => state.options.shouldRandomizeSeed
|
||||
(state: RootState) => state.generation.shouldRandomizeSeed
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -24,7 +24,7 @@ export default function ShuffleSeed() {
|
||||
onClick={handleClickRandomizeSeed}
|
||||
padding="0 1.5rem"
|
||||
>
|
||||
<p>{t('options:shuffle')}</p>
|
||||
<p>{t('parameters:shuffle')}</p>
|
||||
</Button>
|
||||
);
|
||||
}
|
@ -2,13 +2,13 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import { setThreshold } from 'features/options/store/optionsSlice';
|
||||
import { setThreshold } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function Threshold() {
|
||||
const dispatch = useAppDispatch();
|
||||
const threshold = useAppSelector(
|
||||
(state: RootState) => state.options.threshold
|
||||
(state: RootState) => state.generation.threshold
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -16,7 +16,7 @@ export default function Threshold() {
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:noiseThreshold')}
|
||||
label={t('parameters:noiseThreshold')}
|
||||
min={0}
|
||||
max={1000}
|
||||
step={0.1}
|
@ -1,4 +1,4 @@
|
||||
.upscale-options {
|
||||
.upscale-settings {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
column-gap: 1rem;
|
@ -1,42 +1,29 @@
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
|
||||
import { UpscalingLevel } from 'features/parameters/store/postprocessingSlice';
|
||||
import {
|
||||
setUpscalingLevel,
|
||||
setUpscalingStrength,
|
||||
UpscalingLevel,
|
||||
OptionsState,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/postprocessingSlice';
|
||||
|
||||
import { UPSCALING_LEVELS } from 'app/constants';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { isEqual } from 'lodash';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import { ChangeEvent } from 'react';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import IAISelect from 'common/components/IAISelect';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
const optionsSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(options: OptionsState) => {
|
||||
return {
|
||||
upscalingLevel: options.upscalingLevel,
|
||||
upscalingStrength: options.upscalingStrength,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
const parametersSelector = createSelector(
|
||||
[postprocessingSelector, systemSelector],
|
||||
|
||||
const systemSelector = createSelector(
|
||||
(state: RootState) => state.system,
|
||||
(system: SystemState) => {
|
||||
({ upscalingLevel, upscalingStrength }, { isESRGANAvailable }) => {
|
||||
return {
|
||||
isESRGANAvailable: system.isESRGANAvailable,
|
||||
upscalingLevel,
|
||||
upscalingStrength,
|
||||
isESRGANAvailable,
|
||||
};
|
||||
},
|
||||
{
|
||||
@ -49,11 +36,10 @@ const systemSelector = createSelector(
|
||||
/**
|
||||
* Displays upscaling/ESRGAN options (level and strength).
|
||||
*/
|
||||
const UpscaleOptions = () => {
|
||||
const UpscaleSettings = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { upscalingLevel, upscalingStrength } = useAppSelector(optionsSelector);
|
||||
|
||||
const { isESRGANAvailable } = useAppSelector(systemSelector);
|
||||
const { upscalingLevel, upscalingStrength, isESRGANAvailable } =
|
||||
useAppSelector(parametersSelector);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -63,17 +49,17 @@ const UpscaleOptions = () => {
|
||||
const handleChangeStrength = (v: number) => dispatch(setUpscalingStrength(v));
|
||||
|
||||
return (
|
||||
<div className="upscale-options">
|
||||
<div className="upscale-settings">
|
||||
<IAISelect
|
||||
isDisabled={!isESRGANAvailable}
|
||||
label={t('options:scale')}
|
||||
label={t('parameters:scale')}
|
||||
value={upscalingLevel}
|
||||
onChange={handleChangeLevel}
|
||||
validValues={UPSCALING_LEVELS}
|
||||
/>
|
||||
<IAINumberInput
|
||||
isDisabled={!isESRGANAvailable}
|
||||
label={t('options:strength')}
|
||||
label={t('parameters:strength')}
|
||||
step={0.05}
|
||||
min={0}
|
||||
max={1}
|
||||
@ -85,4 +71,4 @@ const UpscaleOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default UpscaleOptions;
|
||||
export default UpscaleSettings;
|
@ -2,7 +2,7 @@ import { ChangeEvent } from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldRunESRGAN } from 'features/options/store/optionsSlice';
|
||||
import { setShouldRunESRGAN } from 'features/parameters/store/postprocessingSlice';
|
||||
|
||||
export default function UpscaleToggle() {
|
||||
const isESRGANAvailable = useAppSelector(
|
||||
@ -10,7 +10,7 @@ export default function UpscaleToggle() {
|
||||
);
|
||||
|
||||
const shouldRunESRGAN = useAppSelector(
|
||||
(state: RootState) => state.options.shouldRunESRGAN
|
||||
(state: RootState) => state.postprocessing.shouldRunESRGAN
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
@ -2,11 +2,11 @@ import React, { ChangeEvent } from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldGenerateVariations } from 'features/options/store/optionsSlice';
|
||||
import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice';
|
||||
|
||||
export default function GenerateVariationsToggle() {
|
||||
const shouldGenerateVariations = useAppSelector(
|
||||
(state: RootState) => state.options.shouldGenerateVariations
|
||||
(state: RootState) => state.generation.shouldGenerateVariations
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
@ -3,16 +3,16 @@ import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAIInput from 'common/components/IAIInput';
|
||||
import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
||||
import { setSeedWeights } from 'features/options/store/optionsSlice';
|
||||
import { setSeedWeights } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function SeedWeights() {
|
||||
const seedWeights = useAppSelector(
|
||||
(state: RootState) => state.options.seedWeights
|
||||
(state: RootState) => state.generation.seedWeights
|
||||
);
|
||||
|
||||
const shouldGenerateVariations = useAppSelector(
|
||||
(state: RootState) => state.options.shouldGenerateVariations
|
||||
(state: RootState) => state.generation.shouldGenerateVariations
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
@ -24,7 +24,7 @@ export default function SeedWeights() {
|
||||
|
||||
return (
|
||||
<IAIInput
|
||||
label={t('options:seedWeights')}
|
||||
label={t('parameters:seedWeights')}
|
||||
value={seedWeights}
|
||||
isInvalid={
|
||||
shouldGenerateVariations &&
|
@ -2,16 +2,16 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import { setVariationAmount } from 'features/options/store/optionsSlice';
|
||||
import { setVariationAmount } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function VariationAmount() {
|
||||
const variationAmount = useAppSelector(
|
||||
(state: RootState) => state.options.variationAmount
|
||||
(state: RootState) => state.generation.variationAmount
|
||||
);
|
||||
|
||||
const shouldGenerateVariations = useAppSelector(
|
||||
(state: RootState) => state.options.shouldGenerateVariations
|
||||
(state: RootState) => state.generation.shouldGenerateVariations
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
@ -22,7 +22,7 @@ export default function VariationAmount() {
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:variationAmount')}
|
||||
label={t('parameters:variationAmount')}
|
||||
value={variationAmount}
|
||||
step={0.01}
|
||||
min={0}
|
@ -5,7 +5,7 @@ import VariationAmount from './VariationAmount';
|
||||
/**
|
||||
* Seed & variation options. Includes iteration, seed, seed randomization, variation options.
|
||||
*/
|
||||
const VariationsOptions = () => {
|
||||
const VariationsSettings = () => {
|
||||
return (
|
||||
<Flex gap={2} direction={'column'}>
|
||||
<VariationAmount />
|
||||
@ -14,4 +14,4 @@ const VariationsOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default VariationsOptions;
|
||||
export default VariationsSettings;
|
@ -2,26 +2,26 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import { setCfgScale } from 'features/options/store/optionsSlice';
|
||||
import { setCfgScale } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function MainCFGScale() {
|
||||
const dispatch = useAppDispatch();
|
||||
const cfgScale = useAppSelector((state: RootState) => state.options.cfgScale);
|
||||
const cfgScale = useAppSelector((state: RootState) => state.generation.cfgScale);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangeCfgScale = (v: number) => dispatch(setCfgScale(v));
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:cfgScale')}
|
||||
label={t('parameters:cfgScale')}
|
||||
step={0.5}
|
||||
min={1.01}
|
||||
max={200}
|
||||
onChange={handleChangeCfgScale}
|
||||
value={cfgScale}
|
||||
width="auto"
|
||||
styleClass="main-option-block"
|
||||
styleClass="main-settings-block"
|
||||
textAlign="center"
|
||||
isInteger={false}
|
||||
/>
|
@ -4,12 +4,12 @@ import { HEIGHTS } from 'app/constants';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISelect from 'common/components/IAISelect';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { setHeight } from 'features/options/store/optionsSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { setHeight } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function MainHeight() {
|
||||
const height = useAppSelector((state: RootState) => state.options.height);
|
||||
const height = useAppSelector((state: RootState) => state.generation.height);
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
@ -20,12 +20,12 @@ export default function MainHeight() {
|
||||
return (
|
||||
<IAISelect
|
||||
isDisabled={activeTabName === 'unifiedCanvas'}
|
||||
label={t('options:height')}
|
||||
label={t('parameters:height')}
|
||||
value={height}
|
||||
flexGrow={1}
|
||||
onChange={handleChangeHeight}
|
||||
validValues={HEIGHTS}
|
||||
styleClass="main-option-block"
|
||||
styleClass="main-settings-block"
|
||||
/>
|
||||
);
|
||||
}
|
@ -5,15 +5,15 @@ import type { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import {
|
||||
OptionsState,
|
||||
GenerationState,
|
||||
setIterations,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const mainIterationsSelector = createSelector(
|
||||
[(state: RootState) => state.options],
|
||||
(options: OptionsState) => {
|
||||
const { iterations } = options;
|
||||
[(state: RootState) => state.generation],
|
||||
(parameters: GenerationState) => {
|
||||
const { iterations } = parameters;
|
||||
|
||||
return {
|
||||
iterations,
|
||||
@ -35,7 +35,7 @@ export default function MainIterations() {
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:images')}
|
||||
label={t('parameters:images')}
|
||||
step={1}
|
||||
min={1}
|
||||
max={9999}
|
||||
@ -43,7 +43,7 @@ export default function MainIterations() {
|
||||
value={iterations}
|
||||
width="auto"
|
||||
labelFontSize={0.5}
|
||||
styleClass="main-option-block"
|
||||
styleClass="main-settings-block"
|
||||
textAlign="center"
|
||||
/>
|
||||
);
|
@ -1,23 +1,23 @@
|
||||
@use '../../../../styles/Mixins/' as *;
|
||||
|
||||
.main-options {
|
||||
.main-settings {
|
||||
display: grid;
|
||||
row-gap: 1rem;
|
||||
}
|
||||
|
||||
.main-options-list {
|
||||
.main-settings-list {
|
||||
display: grid;
|
||||
row-gap: 1rem;
|
||||
}
|
||||
|
||||
.main-options-row {
|
||||
.main-settings-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, auto);
|
||||
column-gap: 0.5rem;
|
||||
max-width: $options-bar-max-width;
|
||||
}
|
||||
|
||||
.main-option-block {
|
||||
.main-settings-block {
|
||||
border-radius: 0.5rem;
|
||||
display: grid !important;
|
||||
grid-template-columns: auto !important;
|
||||
@ -33,10 +33,3 @@
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.advanced-options-checkbox {
|
||||
background-color: var(--background-color-secondary);
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.4rem;
|
||||
font-weight: bold;
|
||||
}
|
@ -7,16 +7,16 @@ import MainWidth from './MainWidth';
|
||||
|
||||
export const inputWidth = 'auto';
|
||||
|
||||
export default function MainOptions() {
|
||||
export default function MainSettings() {
|
||||
return (
|
||||
<div className="main-options">
|
||||
<div className="main-options-list">
|
||||
<div className="main-options-row">
|
||||
<div className="main-settings">
|
||||
<div className="main-settings-list">
|
||||
<div className="main-settings-row">
|
||||
<MainIterations />
|
||||
<MainSteps />
|
||||
<MainCFGScale />
|
||||
</div>
|
||||
<div className="main-options-row">
|
||||
<div className="main-settings-row">
|
||||
<MainWidth />
|
||||
<MainHeight />
|
||||
<MainSampler />
|
@ -1,15 +1,16 @@
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { DIFFUSERS_SAMPLERS, SAMPLERS } from 'app/constants';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISelect from 'common/components/IAISelect';
|
||||
import { setSampler } from 'features/options/store/optionsSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import _ from 'lodash';
|
||||
import { setSampler } from 'features/parameters/store/generationSlice';
|
||||
import { activeModelSelector } from 'features/system/store/systemSelectors';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function MainSampler() {
|
||||
const sampler = useAppSelector((state: RootState) => state.options.sampler);
|
||||
const sampler = useAppSelector(
|
||||
(state: RootState) => state.generation.sampler
|
||||
);
|
||||
const activeModel = useAppSelector(activeModelSelector);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
@ -19,7 +20,7 @@ export default function MainSampler() {
|
||||
|
||||
return (
|
||||
<IAISelect
|
||||
label={t('options:sampler')}
|
||||
label={t('parameters:sampler')}
|
||||
value={sampler}
|
||||
onChange={handleChangeSampler}
|
||||
validValues={
|
@ -2,26 +2,26 @@ import React from 'react';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAINumberInput from 'common/components/IAINumberInput';
|
||||
import { setSteps } from 'features/options/store/optionsSlice';
|
||||
import { setSteps } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function MainSteps() {
|
||||
const dispatch = useAppDispatch();
|
||||
const steps = useAppSelector((state: RootState) => state.options.steps);
|
||||
const steps = useAppSelector((state: RootState) => state.generation.steps);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangeSteps = (v: number) => dispatch(setSteps(v));
|
||||
|
||||
return (
|
||||
<IAINumberInput
|
||||
label={t('options:steps')}
|
||||
label={t('parameters:steps')}
|
||||
min={1}
|
||||
max={9999}
|
||||
step={1}
|
||||
onChange={handleChangeSteps}
|
||||
value={steps}
|
||||
width="auto"
|
||||
styleClass="main-option-block"
|
||||
styleClass="main-settings-block"
|
||||
textAlign="center"
|
||||
/>
|
||||
);
|
@ -3,12 +3,12 @@ import { WIDTHS } from 'app/constants';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAISelect from 'common/components/IAISelect';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { setWidth } from 'features/options/store/optionsSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { setWidth } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function MainWidth() {
|
||||
const width = useAppSelector((state: RootState) => state.options.width);
|
||||
const width = useAppSelector((state: RootState) => state.generation.width);
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -20,12 +20,12 @@ export default function MainWidth() {
|
||||
return (
|
||||
<IAISelect
|
||||
isDisabled={activeTabName === 'unifiedCanvas'}
|
||||
label={t('options:width')}
|
||||
label={t('parameters:width')}
|
||||
value={width}
|
||||
flexGrow={1}
|
||||
onChange={handleChangeWidth}
|
||||
validValues={WIDTHS}
|
||||
styleClass="main-option-block"
|
||||
styleClass="main-settings-block"
|
||||
/>
|
||||
);
|
||||
}
|
@ -7,18 +7,18 @@ import InvokeAccordionItem, {
|
||||
} from './AccordionItems/InvokeAccordionItem';
|
||||
import { ReactElement } from 'react';
|
||||
|
||||
type OptionsAccordionType = {
|
||||
[optionAccordionKey: string]: InvokeAccordionItemProps;
|
||||
type ParametersAccordionType = {
|
||||
[parametersAccordionKey: string]: InvokeAccordionItemProps;
|
||||
};
|
||||
|
||||
type OptionAccordionsType = {
|
||||
accordionInfo: OptionsAccordionType;
|
||||
type ParametersAccordionsType = {
|
||||
accordionInfo: ParametersAccordionType;
|
||||
};
|
||||
|
||||
/**
|
||||
* Main container for generation and processing parameters.
|
||||
*/
|
||||
const OptionsAccordion = (props: OptionAccordionsType) => {
|
||||
const ParametersAccordion = (props: ParametersAccordionsType) => {
|
||||
const { accordionInfo } = props;
|
||||
|
||||
const openAccordions = useAppSelector(
|
||||
@ -59,11 +59,11 @@ const OptionsAccordion = (props: OptionAccordionsType) => {
|
||||
allowMultiple
|
||||
reduceMotion
|
||||
onChange={handleChangeAccordionState}
|
||||
className="advanced-settings"
|
||||
className="advanced-parameters"
|
||||
>
|
||||
{renderAccordions()}
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
export default OptionsAccordion;
|
||||
export default ParametersAccordion;
|
@ -1,6 +1,5 @@
|
||||
import { MdCancel } from 'react-icons/md';
|
||||
import { cancelProcessing } from 'app/socketio/actions';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAIIconButton, {
|
||||
IAIIconButtonProps,
|
||||
@ -10,9 +9,10 @@ import { createSelector } from '@reduxjs/toolkit';
|
||||
import { SystemState } from 'features/system/store/systemSlice';
|
||||
import _ from 'lodash';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
|
||||
const cancelButtonSelector = createSelector(
|
||||
(state: RootState) => state.system,
|
||||
systemSelector,
|
||||
(system: SystemState) => {
|
||||
return {
|
||||
isProcessing: system.isProcessing,
|
||||
@ -51,8 +51,8 @@ export default function CancelButton(
|
||||
return (
|
||||
<IAIIconButton
|
||||
icon={<MdCancel />}
|
||||
tooltip={t('options:cancel')}
|
||||
aria-label={t('options:cancel')}
|
||||
tooltip={t('parameters:cancel')}
|
||||
aria-label={t('parameters:cancel')}
|
||||
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
||||
onClick={handleClickCancel}
|
||||
styleClass="cancel-btn"
|
@ -7,7 +7,7 @@ import IAIButton, { IAIButtonProps } from 'common/components/IAIButton';
|
||||
import IAIIconButton, {
|
||||
IAIIconButtonProps,
|
||||
} from 'common/components/IAIIconButton';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface InvokeButton
|
||||
@ -44,19 +44,19 @@ export default function InvokeButton(props: InvokeButton) {
|
||||
<div style={{ flexGrow: 4 }}>
|
||||
{iconButton ? (
|
||||
<IAIIconButton
|
||||
aria-label={t('options:invoke')}
|
||||
aria-label={t('parameters:invoke')}
|
||||
type="submit"
|
||||
icon={<FaPlay />}
|
||||
isDisabled={!isReady}
|
||||
onClick={handleClickGenerate}
|
||||
className="invoke-btn"
|
||||
tooltip={t('options:invoke')}
|
||||
tooltip={t('parameters:invoke')}
|
||||
tooltipProps={{ placement: 'bottom' }}
|
||||
{...rest}
|
||||
/>
|
||||
) : (
|
||||
<IAIButton
|
||||
aria-label={t('options:invoke')}
|
||||
aria-label={t('parameters:invoke')}
|
||||
type="submit"
|
||||
isDisabled={!isReady}
|
||||
onClick={handleClickGenerate}
|
@ -1,17 +1,14 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { FaRecycle } from 'react-icons/fa';
|
||||
import { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import {
|
||||
OptionsState,
|
||||
setShouldLoopback,
|
||||
} from 'features/options/store/optionsSlice';
|
||||
import { setShouldLoopback } from 'features/parameters/store/postprocessingSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
|
||||
|
||||
const loopbackSelector = createSelector(
|
||||
(state: RootState) => state.options,
|
||||
(options: OptionsState) => options.shouldLoopback
|
||||
postprocessingSelector,
|
||||
({ shouldLoopback }) => shouldLoopback
|
||||
);
|
||||
|
||||
const LoopbackButton = () => {
|
||||
@ -22,8 +19,8 @@ const LoopbackButton = () => {
|
||||
|
||||
return (
|
||||
<IAIIconButton
|
||||
aria-label={t('options:toggleLoopback')}
|
||||
tooltip={t('options:toggleLoopback')}
|
||||
aria-label={t('parameters:toggleLoopback')}
|
||||
tooltip={t('parameters:toggleLoopback')}
|
||||
styleClass="loopback-btn"
|
||||
asCheckbox={true}
|
||||
isChecked={shouldLoopback}
|
@ -2,7 +2,7 @@ import InvokeButton from './InvokeButton';
|
||||
import CancelButton from './CancelButton';
|
||||
import LoopbackButton from './Loopback';
|
||||
import { useAppSelector } from 'app/storeHooks';
|
||||
import { activeTabNameSelector } from 'features/options/store/optionsSelectors';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
|
||||
/**
|
||||
* Buttons to start and cancel image generation.
|
@ -1,12 +1,12 @@
|
||||
import { FormControl, Textarea } from '@chakra-ui/react';
|
||||
import type { RootState } from 'app/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/storeHooks';
|
||||
import { setNegativePrompt } from 'features/options/store/optionsSlice';
|
||||
import { setNegativePrompt } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export function NegativePromptInput() {
|
||||
const NegativePromptInput = () => {
|
||||
const negativePrompt = useAppSelector(
|
||||
(state: RootState) => state.options.negativePrompt
|
||||
(state: RootState) => state.generation.negativePrompt
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
@ -20,7 +20,7 @@ export function NegativePromptInput() {
|
||||
value={negativePrompt}
|
||||
onChange={(e) => dispatch(setNegativePrompt(e.target.value))}
|
||||
background="var(--prompt-bg-color)"
|
||||
placeholder={t('options:negativePrompts')}
|
||||
placeholder={t('parameters:negativePrompts')}
|
||||
_placeholder={{ fontSize: '0.8rem' }}
|
||||
borderColor="var(--border-color)"
|
||||
_hover={{
|
||||
@ -35,4 +35,6 @@ export function NegativePromptInput() {
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default NegativePromptInput;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user