mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): update most other selectors
Just a few stragglers left. Good enough for now.
This commit is contained in:
parent
b71b14d582
commit
3c4150d153
@ -1,7 +1,6 @@
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectGallerySlice } from 'features/gallery/store/gallerySlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import type { Accept, FileRejection } from 'react-dropzone';
|
||||
@ -15,9 +14,9 @@ const accept: Accept = {
|
||||
'image/jpeg': ['.jpg', '.jpeg', '.png'],
|
||||
};
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectGallerySlice, activeTabNameSelector],
|
||||
(gallery, activeTabName) => {
|
||||
const selectPostUploadAction = createMemoizedSelector(
|
||||
activeTabNameSelector,
|
||||
(activeTabName) => {
|
||||
let postUploadAction: PostUploadAction = { type: 'TOAST' };
|
||||
|
||||
if (activeTabName === 'unifiedCanvas') {
|
||||
@ -28,19 +27,15 @@ const selector = createMemoizedSelector(
|
||||
postUploadAction = { type: 'SET_INITIAL_IMAGE' };
|
||||
}
|
||||
|
||||
const { autoAddBoardId } = gallery;
|
||||
|
||||
return {
|
||||
autoAddBoardId,
|
||||
postUploadAction,
|
||||
};
|
||||
return postUploadAction;
|
||||
}
|
||||
);
|
||||
|
||||
export const useFullscreenDropzone = () => {
|
||||
const { autoAddBoardId, postUploadAction } = useAppSelector(selector);
|
||||
const toaster = useAppToaster();
|
||||
const { t } = useTranslation();
|
||||
const toaster = useAppToaster();
|
||||
const postUploadAction = useAppSelector(selectPostUploadAction);
|
||||
const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId);
|
||||
const [isHandlingUpload, setIsHandlingUpload] = useState<boolean>(false);
|
||||
|
||||
const [uploadImage] = useUploadImageMutation();
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
setIsDrawing,
|
||||
setIsMovingStage,
|
||||
} from 'features/canvas/store/canvasNanostore';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import { addLine, selectCanvasSlice } from 'features/canvas/store/canvasSlice';
|
||||
import { addLine } from 'features/canvas/store/canvasSlice';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import type Konva from 'konva';
|
||||
import type { KonvaEventObject } from 'konva/lib/Node';
|
||||
import type { MutableRefObject } from 'react';
|
||||
@ -15,20 +13,10 @@ import { useCallback } from 'react';
|
||||
|
||||
import useColorPicker from './useColorUnderCursor';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[activeTabNameSelector, selectCanvasSlice, isStagingSelector],
|
||||
(activeTabName, canvas, isStaging) => {
|
||||
return {
|
||||
tool: canvas.tool,
|
||||
activeTabName,
|
||||
isStaging,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const useCanvasMouseDown = (stageRef: MutableRefObject<Konva.Stage | null>) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { tool, isStaging } = useAppSelector(selector);
|
||||
const tool = useAppSelector((s) => s.canvas.tool);
|
||||
const isStaging = useAppSelector(isStagingSelector);
|
||||
const { commitColorUnderCursor } = useColorPicker();
|
||||
|
||||
return useCallback(
|
||||
|
@ -5,9 +5,7 @@ import {
|
||||
setCursorPosition,
|
||||
} from 'features/canvas/store/canvasNanostore';
|
||||
import { isStagingSelector } from 'features/canvas/store/canvasSelectors';
|
||||
import {
|
||||
addPointToCurrentLine,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { addPointToCurrentLine } from 'features/canvas/store/canvasSlice';
|
||||
import getScaledCursorPosition from 'features/canvas/util/getScaledCursorPosition';
|
||||
import type Konva from 'konva';
|
||||
import type { Vector2d } from 'konva/lib/types';
|
||||
|
@ -1,18 +1,17 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import type { RootState } from 'app/store/store';
|
||||
|
||||
import { selectCanvasSlice } from './canvasSlice';
|
||||
import type { CanvasImage } from './canvasTypes';
|
||||
import { isCanvasBaseImage } from './canvasTypes';
|
||||
|
||||
export const isStagingSelector = createMemoizedSelector(
|
||||
export const isStagingSelector = createSelector(
|
||||
selectCanvasSlice,
|
||||
(canvas) =>
|
||||
canvas.batchIds.length > 0 ||
|
||||
canvas.layerState.stagingArea.images.length > 0
|
||||
);
|
||||
|
||||
export const initialCanvasImageSelector = (
|
||||
state: RootState
|
||||
): CanvasImage | undefined =>
|
||||
state.canvas.layerState.objects.find(isCanvasBaseImage);
|
||||
export const initialCanvasImageSelector = createMemoizedSelector(
|
||||
selectCanvasSlice,
|
||||
(canvas) => canvas.layerState.objects.find(isCanvasBaseImage)
|
||||
);
|
||||
|
@ -22,23 +22,17 @@ import {
|
||||
useRemoveImagesFromBoardMutation,
|
||||
} from 'services/api/endpoints/images';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selectImagesToChange = createMemoizedSelector(
|
||||
selectChangeBoardModalSlice,
|
||||
(changeBoardModal) => {
|
||||
const { isModalOpen, imagesToChange } = changeBoardModal;
|
||||
|
||||
return {
|
||||
isModalOpen,
|
||||
imagesToChange,
|
||||
};
|
||||
}
|
||||
(changeBoardModal) => changeBoardModal.imagesToChange
|
||||
);
|
||||
|
||||
const ChangeBoardModal = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const [selectedBoard, setSelectedBoard] = useState<string | null>();
|
||||
const { data: boards, isFetching } = useListAllBoardsQuery();
|
||||
const { imagesToChange, isModalOpen } = useAppSelector(selector);
|
||||
const isModalOpen = useAppSelector((s) => s.changeBoardModal.isModalOpen);
|
||||
const imagesToChange = useAppSelector(selectImagesToChange);
|
||||
const [addImagesToBoard] = useAddImagesToBoardMutation();
|
||||
const [removeImagesFromBoard] = useRemoveImagesFromBoardMutation();
|
||||
const { t } = useTranslation();
|
||||
|
@ -17,14 +17,11 @@ import type {
|
||||
TypesafeDraggableData,
|
||||
TypesafeDroppableData,
|
||||
} from 'features/dnd/types';
|
||||
import { selectGallerySlice } from 'features/gallery/store/gallerySlice';
|
||||
import {
|
||||
heightChanged,
|
||||
selectOptimalDimension,
|
||||
widthChanged,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { selectSystemSlice } from 'features/system/store/systemSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaRulerVertical, FaSave, FaUndo } from 'react-icons/fa';
|
||||
@ -41,42 +38,22 @@ type Props = {
|
||||
isSmall?: boolean;
|
||||
};
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[
|
||||
selectControlAdaptersSlice,
|
||||
selectGallerySlice,
|
||||
selectSystemSlice,
|
||||
activeTabNameSelector,
|
||||
selectOptimalDimension,
|
||||
],
|
||||
(controlAdapters, gallery, system, activeTabName, optimalDimension) => {
|
||||
const { pendingControlImages } = controlAdapters;
|
||||
const { autoAddBoardId } = gallery;
|
||||
const { isConnected } = system;
|
||||
|
||||
return {
|
||||
pendingControlImages,
|
||||
autoAddBoardId,
|
||||
isConnected,
|
||||
activeTabName,
|
||||
optimalDimension,
|
||||
};
|
||||
}
|
||||
const selectPendingControlImages = createMemoizedSelector(
|
||||
selectControlAdaptersSlice,
|
||||
(controlAdapters) => controlAdapters.pendingControlImages
|
||||
);
|
||||
|
||||
const ControlAdapterImagePreview = ({ isSmall, id }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const controlImageName = useControlAdapterControlImage(id);
|
||||
const processedControlImageName = useControlAdapterProcessedControlImage(id);
|
||||
const processorType = useControlAdapterProcessorType(id);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
pendingControlImages,
|
||||
autoAddBoardId,
|
||||
isConnected,
|
||||
activeTabName,
|
||||
optimalDimension,
|
||||
} = useAppSelector(selector);
|
||||
const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId);
|
||||
const isConnected = useAppSelector((s) => s.system.isConnected);
|
||||
const activeTabName = useAppSelector(selectActiveTabname);
|
||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||
const pendingControlImages = useAppSelector(selectPendingControlImages);
|
||||
|
||||
const [isMouseOverImage, setIsMouseOverImage] = useState(false);
|
||||
|
||||
|
@ -24,9 +24,10 @@ type ParamControlAdapterModelProps = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
const selector = createMemoizedSelector(selectGenerationSlice, (generation) => {
|
||||
return { mainModel: generation.model };
|
||||
});
|
||||
const selectMainModel = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
(generation) => generation.model
|
||||
);
|
||||
|
||||
const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => {
|
||||
const isEnabled = useControlAdapterIsEnabled(id);
|
||||
@ -36,7 +37,7 @@ const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => {
|
||||
const currentBaseModel = useAppSelector(
|
||||
(s) => s.generation.model?.base_model
|
||||
);
|
||||
const { mainModel } = useAppSelector(selector);
|
||||
const { mainModel } = useAppSelector(selectMainModel);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const models = useControlAdapterModelEntities(controlAdapterType);
|
||||
|
@ -20,7 +20,7 @@ type Props = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
const selector = createMemoizedSelector(configSelector, (config) => {
|
||||
const selectOptions = createMemoizedSelector(configSelector, (config) => {
|
||||
const options: InvSelectOption[] = map(CONTROLNET_PROCESSORS, (p) => ({
|
||||
value: p.type,
|
||||
label: p.label,
|
||||
@ -47,7 +47,7 @@ const ParamControlAdapterProcessorSelect = ({ id }: Props) => {
|
||||
const isEnabled = useControlAdapterIsEnabled(id);
|
||||
const processorNode = useControlAdapterProcessorNode(id);
|
||||
const dispatch = useAppDispatch();
|
||||
const options = useAppSelector(selector);
|
||||
const options = useAppSelector(selectOptions);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const onChange = useCallback<InvSelectOnChange>(
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -9,7 +9,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterControlImage = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectControlAdaptersSlice,
|
||||
(controlAdapters) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.controlImage
|
||||
@ -17,7 +17,7 @@ export const useControlAdapterControlImage = (id: string) => {
|
||||
[id]
|
||||
);
|
||||
|
||||
const weight = useAppSelector(selector);
|
||||
const controlImageName = useAppSelector(selector);
|
||||
|
||||
return weight;
|
||||
return controlImageName;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -10,7 +10,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterControlMode = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
createSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNet(ca)) {
|
||||
return ca.controlMode;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -9,7 +9,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterIsEnabled = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectControlAdaptersSlice,
|
||||
(controlAdapters) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.isEnabled ?? false
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -10,7 +10,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterProcessedControlImage = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
createSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -10,7 +10,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterProcessorType = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
createSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
|
||||
return ca && isControlNetOrT2IAdapter(ca)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -10,7 +10,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterShouldAutoConfig = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
createSelector(selectControlAdaptersSlice, (controlAdapters) => {
|
||||
const ca = selectControlAdapterById(controlAdapters, id);
|
||||
if (ca && isControlNetOrT2IAdapter(ca)) {
|
||||
return ca.shouldAutoConfig;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
selectControlAdapterById,
|
||||
@ -9,7 +9,7 @@ import { useMemo } from 'react';
|
||||
export const useControlAdapterWeight = (id: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectControlAdaptersSlice,
|
||||
(controlAdapters) =>
|
||||
selectControlAdapterById(controlAdapters, id)?.weight
|
||||
|
@ -20,11 +20,7 @@ import {
|
||||
import type { ImageUsage } from 'features/deleteImageModal/store/types';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { selectGenerationSlice } from 'features/parameters/store/generationSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import {
|
||||
selectSystemSlice,
|
||||
setShouldConfirmOnDelete,
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { setShouldConfirmOnDelete } from 'features/system/store/systemSlice';
|
||||
import { some } from 'lodash-es';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
@ -32,10 +28,8 @@ import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ImageUsageMessage from './ImageUsageMessage';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selectImageUsages = createMemoizedSelector(
|
||||
[
|
||||
selectSystemSlice,
|
||||
selectConfigSlice,
|
||||
selectDeleteImageModalSlice,
|
||||
selectGenerationSlice,
|
||||
selectCanvasSlice,
|
||||
@ -44,8 +38,6 @@ const selector = createMemoizedSelector(
|
||||
selectImageUsage,
|
||||
],
|
||||
(
|
||||
system,
|
||||
config,
|
||||
deleteImageModal,
|
||||
generation,
|
||||
canvas,
|
||||
@ -53,9 +45,7 @@ const selector = createMemoizedSelector(
|
||||
controlAdapters,
|
||||
imagesUsage
|
||||
) => {
|
||||
const { shouldConfirmOnDelete } = system;
|
||||
const { canRestoreDeletedImagesFromBin } = config;
|
||||
const { imagesToDelete, isModalOpen } = deleteImageModal;
|
||||
const { imagesToDelete } = deleteImageModal;
|
||||
|
||||
const allImageUsage = (imagesToDelete ?? []).map(({ image_name }) =>
|
||||
getImageUsage(generation, canvas, nodes, controlAdapters, image_name)
|
||||
@ -69,11 +59,8 @@ const selector = createMemoizedSelector(
|
||||
};
|
||||
|
||||
return {
|
||||
shouldConfirmOnDelete,
|
||||
canRestoreDeletedImagesFromBin,
|
||||
imagesToDelete,
|
||||
imagesUsage,
|
||||
isModalOpen,
|
||||
imageUsageSummary,
|
||||
};
|
||||
}
|
||||
@ -82,15 +69,15 @@ const selector = createMemoizedSelector(
|
||||
const DeleteImageModal = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const {
|
||||
shouldConfirmOnDelete,
|
||||
canRestoreDeletedImagesFromBin,
|
||||
imagesToDelete,
|
||||
imagesUsage,
|
||||
isModalOpen,
|
||||
imageUsageSummary,
|
||||
} = useAppSelector(selector);
|
||||
const shouldConfirmOnDelete = useAppSelector(
|
||||
(s) => s.system.shouldConfirmOnDelete
|
||||
);
|
||||
const canRestoreDeletedImagesFromBin = useAppSelector(
|
||||
(s) => s.config.canRestoreDeletedImagesFromBin
|
||||
);
|
||||
const isModalOpen = useAppSelector((s) => s.deleteImageModal.isModalOpen);
|
||||
const { imagesToDelete, imagesUsage, imageUsageSummary } =
|
||||
useAppSelector(selectImageUsages);
|
||||
|
||||
const handleChangeShouldConfirmOnDelete = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) =>
|
||||
|
@ -1,37 +1,23 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import {
|
||||
maxPromptsChanged,
|
||||
selectDynamicPromptsSlice,
|
||||
} from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { maxPromptsChanged } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectDynamicPromptsSlice,
|
||||
selectConfigSlice,
|
||||
(dynamicPrompts, config) => {
|
||||
const { maxPrompts, combinatorial } = dynamicPrompts;
|
||||
const { min, sliderMax, inputMax, initial } =
|
||||
config.sd.dynamicPrompts.maxPrompts;
|
||||
|
||||
return {
|
||||
maxPrompts,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
initial,
|
||||
isDisabled: !combinatorial,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamDynamicPromptsMaxPrompts = () => {
|
||||
const { maxPrompts, min, sliderMax, inputMax, initial, isDisabled } =
|
||||
useAppSelector(selector);
|
||||
const maxPrompts = useAppSelector((s) => s.dynamicPrompts.maxPrompts);
|
||||
const min = useAppSelector((s) => s.config.sd.dynamicPrompts.maxPrompts.min);
|
||||
const sliderMax = useAppSelector(
|
||||
(s) => s.config.sd.dynamicPrompts.maxPrompts.sliderMax
|
||||
);
|
||||
const inputMax = useAppSelector(
|
||||
(s) => s.config.sd.dynamicPrompts.maxPrompts.inputMax
|
||||
);
|
||||
const initial = useAppSelector(
|
||||
(s) => s.config.sd.dynamicPrompts.maxPrompts.initial
|
||||
);
|
||||
const isDisabled = useAppSelector((s) => !s.dynamicPrompts.combinatorial);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -11,18 +11,9 @@ import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaCircleExclamation } from 'react-icons/fa6';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selectPrompts = createMemoizedSelector(
|
||||
selectDynamicPromptsSlice,
|
||||
(dynamicPrompts) => {
|
||||
const { isLoading, isError, prompts, parsingError } = dynamicPrompts;
|
||||
|
||||
return {
|
||||
prompts,
|
||||
parsingError,
|
||||
isError,
|
||||
isLoading,
|
||||
};
|
||||
}
|
||||
(dynamicPrompts) => dynamicPrompts.prompts
|
||||
);
|
||||
|
||||
const listItemStyles: ChakraProps['sx'] = {
|
||||
@ -31,8 +22,10 @@ const listItemStyles: ChakraProps['sx'] = {
|
||||
|
||||
const ParamDynamicPromptsPreview = () => {
|
||||
const { t } = useTranslation();
|
||||
const { prompts, parsingError, isLoading, isError } =
|
||||
useAppSelector(selector);
|
||||
const parsingError = useAppSelector((s) => s.dynamicPrompts.parsingError);
|
||||
const isError = useAppSelector((s) => s.dynamicPrompts.isError);
|
||||
const isLoading = useAppSelector((s) => s.dynamicPrompts.isLoading);
|
||||
const prompts = useAppSelector(selectPrompts);
|
||||
|
||||
const label = useMemo(() => {
|
||||
let _label = `${t('dynamicPrompts.promptsPreview')} (${prompts.length})`;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import type { InvContextMenuProps } from 'common/components/InvContextMenu/InvContextMenu';
|
||||
import { InvContextMenu } from 'common/components/InvContextMenu/InvContextMenu';
|
||||
@ -37,18 +37,19 @@ const BoardContextMenu = ({
|
||||
}: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const selector = useMemo(
|
||||
const autoAssignBoardOnClick = useAppSelector(
|
||||
(s) => s.gallery.autoAssignBoardOnClick
|
||||
);
|
||||
const selectIsSelectedForAutoAdd = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectGallerySlice, (gallery) => {
|
||||
const isAutoAdd = gallery.autoAddBoardId === board_id;
|
||||
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
|
||||
return { isAutoAdd, autoAssignBoardOnClick };
|
||||
}),
|
||||
[board_id]
|
||||
createSelector(
|
||||
selectGallerySlice,
|
||||
(gallery) => board && board.board_id === gallery.autoAddBoardId
|
||||
),
|
||||
[board]
|
||||
);
|
||||
|
||||
const { isAutoAdd, autoAssignBoardOnClick } = useAppSelector(selector);
|
||||
const isSelectedForAutoAdd = useAppSelector(selectIsSelectedForAutoAdd);
|
||||
const boardName = useBoardName(board_id);
|
||||
const isBulkDownloadEnabled =
|
||||
useFeatureStatus('bulkDownload').isFeatureEnabled;
|
||||
@ -99,7 +100,7 @@ const BoardContextMenu = ({
|
||||
<InvMenuGroup title={boardName}>
|
||||
<InvMenuItem
|
||||
icon={<FaPlus />}
|
||||
isDisabled={isAutoAdd || autoAssignBoardOnClick}
|
||||
isDisabled={isSelectedForAutoAdd || autoAssignBoardOnClick}
|
||||
onClick={handleSetAutoAdd}
|
||||
>
|
||||
{t('boards.menuItemAutoAdd')}
|
||||
@ -127,8 +128,8 @@ const BoardContextMenu = ({
|
||||
boardName,
|
||||
handleBulkDownload,
|
||||
handleSetAutoAdd,
|
||||
isAutoAdd,
|
||||
isBulkDownloadEnabled,
|
||||
isSelectedForAutoAdd,
|
||||
setBoardToDelete,
|
||||
skipEvent,
|
||||
t,
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
Icon,
|
||||
Image,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIDroppable from 'common/components/IAIDroppable';
|
||||
import { InvText } from 'common/components/InvText/wrapper';
|
||||
@ -54,22 +54,19 @@ const GalleryBoard = ({
|
||||
setBoardToDelete,
|
||||
}: GalleryBoardProps) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const selector = useMemo(
|
||||
const autoAssignBoardOnClick = useAppSelector(
|
||||
(s) => s.gallery.autoAssignBoardOnClick
|
||||
);
|
||||
const selectIsSelectedForAutoAdd = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectGallerySlice, (gallery) => {
|
||||
const isSelectedForAutoAdd = board.board_id === gallery.autoAddBoardId;
|
||||
const autoAssignBoardOnClick = gallery.autoAssignBoardOnClick;
|
||||
|
||||
return {
|
||||
isSelectedForAutoAdd,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
}),
|
||||
createSelector(
|
||||
selectGallerySlice,
|
||||
(gallery) => board.board_id === gallery.autoAddBoardId
|
||||
),
|
||||
[board.board_id]
|
||||
);
|
||||
|
||||
const { isSelectedForAutoAdd, autoAssignBoardOnClick } =
|
||||
useAppSelector(selector);
|
||||
const isSelectedForAutoAdd = useAppSelector(selectIsSelectedForAutoAdd);
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const handleMouseOver = useCallback(() => {
|
||||
setIsHovered(true);
|
||||
|
@ -63,7 +63,8 @@ const DeleteBoardModal = (props: Props) => {
|
||||
isNodesImage: some(allImageUsage, (i) => i.isNodesImage),
|
||||
isControlImage: some(allImageUsage, (i) => i.isControlImage),
|
||||
};
|
||||
return { imageUsageSummary };
|
||||
|
||||
return imageUsageSummary;
|
||||
}
|
||||
),
|
||||
[boardImageNames]
|
||||
@ -75,7 +76,7 @@ const DeleteBoardModal = (props: Props) => {
|
||||
const [deleteBoardAndImages, { isLoading: isDeleteBoardAndImagesLoading }] =
|
||||
useDeleteBoardAndImagesMutation();
|
||||
|
||||
const { imageUsageSummary } = useAppSelector(selectImageUsageSummary);
|
||||
const imageUsageSummary = useAppSelector(selectImageUsageSummary);
|
||||
|
||||
const handleDeleteBoardOnly = useCallback(() => {
|
||||
if (!boardToDelete) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useAppToaster } from 'app/components/Toaster';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { upscaleRequested } from 'app/store/middleware/listenerMiddleware/listeners/upscaleRequested';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvButtonGroup } from 'common/components/InvButtonGroup/InvButtonGroup';
|
||||
@ -12,17 +12,15 @@ import { DeleteImageButton } from 'features/deleteImageModal/components/DeleteIm
|
||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||
import SingleSelectionMenuItems from 'features/gallery/components/ImageContextMenu/SingleSelectionMenuItems';
|
||||
import { sentImageToImg2Img } from 'features/gallery/store/actions';
|
||||
import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors';
|
||||
import { selectGallerySlice } from 'features/gallery/store/gallerySlice';
|
||||
import ParamUpscalePopover from 'features/parameters/components/Upscale/ParamUpscaleSettings';
|
||||
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
|
||||
import { initialImageSelected } from 'features/parameters/store/actions';
|
||||
import { useIsQueueMutationInProgress } from 'features/queue/hooks/useIsQueueMutationInProgress';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { selectSystemSlice } from 'features/system/store/systemSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import {
|
||||
selectUiSlice,
|
||||
setShouldShowImageDetails,
|
||||
setShouldShowProgressInViewer,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
@ -42,51 +40,29 @@ import { FaCircleNodes, FaEllipsis } from 'react-icons/fa6';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||
|
||||
const currentImageButtonsSelector = createMemoizedSelector(
|
||||
[
|
||||
selectGallerySlice,
|
||||
selectSystemSlice,
|
||||
selectUiSlice,
|
||||
selectConfigSlice,
|
||||
activeTabNameSelector,
|
||||
],
|
||||
(gallery, system, ui, config, activeTabName) => {
|
||||
const { isConnected, shouldConfirmOnDelete, denoiseProgress } = system;
|
||||
|
||||
const {
|
||||
shouldShowImageDetails,
|
||||
shouldHidePreview,
|
||||
shouldShowProgressInViewer,
|
||||
} = ui;
|
||||
|
||||
const { shouldFetchMetadataFromApi } = config;
|
||||
|
||||
const lastSelectedImage = gallery.selection[gallery.selection.length - 1];
|
||||
|
||||
return {
|
||||
shouldConfirmOnDelete,
|
||||
isConnected,
|
||||
shouldDisableToolbarButtons:
|
||||
Boolean(denoiseProgress?.progress_image) || !lastSelectedImage,
|
||||
shouldShowImageDetails,
|
||||
activeTabName,
|
||||
shouldHidePreview,
|
||||
shouldShowProgressInViewer,
|
||||
lastSelectedImage,
|
||||
shouldFetchMetadataFromApi,
|
||||
};
|
||||
const selectShouldDisableToolbarButtons = createSelector(
|
||||
selectSystemSlice,
|
||||
selectGallerySlice,
|
||||
selectLastSelectedImage,
|
||||
(system, gallery, lastSelectedImage) => {
|
||||
const hasProgressImage = Boolean(system.denoiseProgress?.progress_image);
|
||||
return hasProgressImage || !lastSelectedImage;
|
||||
}
|
||||
);
|
||||
|
||||
const CurrentImageButtons = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const {
|
||||
isConnected,
|
||||
shouldDisableToolbarButtons,
|
||||
shouldShowImageDetails,
|
||||
lastSelectedImage,
|
||||
shouldShowProgressInViewer,
|
||||
} = useAppSelector(currentImageButtonsSelector);
|
||||
const isConnected = useAppSelector((s) => s.system.isConnected);
|
||||
const shouldShowImageDetails = useAppSelector(
|
||||
(s) => s.ui.shouldShowImageDetails
|
||||
);
|
||||
const shouldShowProgressInViewer = useAppSelector(
|
||||
(s) => s.ui.shouldShowProgressInViewer
|
||||
);
|
||||
const lastSelectedImage = useAppSelector(selectLastSelectedImage);
|
||||
const shouldDisableToolbarButtons = useAppSelector(
|
||||
selectShouldDisableToolbarButtons
|
||||
);
|
||||
|
||||
const isUpscalingEnabled = useFeatureStatus('upscaling').isFeatureEnabled;
|
||||
const isQueueMutationInProgress = useIsQueueMutationInProgress();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIDndImage from 'common/components/IAIDndImage';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
@ -13,8 +13,6 @@ import ImageMetadataViewer from 'features/gallery/components/ImageMetadataViewer
|
||||
import NextPrevImageButtons from 'features/gallery/components/NextPrevImageButtons';
|
||||
import { useNextPrevImage } from 'features/gallery/hooks/useNextPrevImage';
|
||||
import { selectLastSelectedImage } from 'features/gallery/store/gallerySelectors';
|
||||
import { selectSystemSlice } from 'features/system/store/systemSlice';
|
||||
import { selectUiSlice } from 'features/ui/store/uiSlice';
|
||||
import type { AnimationProps } from 'framer-motion';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import type { CSSProperties } from 'react';
|
||||
@ -24,34 +22,22 @@ import { useTranslation } from 'react-i18next';
|
||||
import { FaImage } from 'react-icons/fa';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
|
||||
export const imagesSelector = createMemoizedSelector(
|
||||
selectUiSlice,
|
||||
selectSystemSlice,
|
||||
const selectLastSelectedImageName = createSelector(
|
||||
selectLastSelectedImage,
|
||||
(ui, system, lastSelectedImage) => {
|
||||
const {
|
||||
shouldShowImageDetails,
|
||||
shouldHidePreview,
|
||||
shouldShowProgressInViewer,
|
||||
} = ui;
|
||||
const { denoiseProgress } = system;
|
||||
return {
|
||||
shouldShowImageDetails,
|
||||
shouldHidePreview,
|
||||
imageName: lastSelectedImage?.image_name,
|
||||
hasDenoiseProgress: Boolean(denoiseProgress),
|
||||
shouldShowProgressInViewer,
|
||||
};
|
||||
}
|
||||
(lastSelectedImage) => lastSelectedImage?.image_name
|
||||
);
|
||||
|
||||
const CurrentImagePreview = () => {
|
||||
const {
|
||||
shouldShowImageDetails,
|
||||
imageName,
|
||||
hasDenoiseProgress,
|
||||
shouldShowProgressInViewer,
|
||||
} = useAppSelector(imagesSelector);
|
||||
const shouldShowImageDetails = useAppSelector(
|
||||
(s) => s.ui.shouldShowImageDetails
|
||||
);
|
||||
const imageName = useAppSelector(selectLastSelectedImageName);
|
||||
const hasDenoiseProgress = useAppSelector((s) =>
|
||||
Boolean(s.system.denoiseProgress)
|
||||
);
|
||||
const shouldShowProgressInViewer = useAppSelector(
|
||||
(s) => s.ui.shouldShowProgressInViewer
|
||||
);
|
||||
|
||||
const {
|
||||
handlePrevImage,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvCheckbox } from 'common/components/InvCheckbox/wrapper';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
@ -14,7 +13,6 @@ import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import { InvSwitch } from 'common/components/InvSwitch/wrapper';
|
||||
import {
|
||||
autoAssignBoardOnClickChanged,
|
||||
selectGallerySlice,
|
||||
setGalleryImageMinimumWidth,
|
||||
shouldAutoSwitchChanged,
|
||||
} from 'features/gallery/store/gallerySlice';
|
||||
@ -25,23 +23,16 @@ import { FaWrench } from 'react-icons/fa';
|
||||
|
||||
import BoardAutoAddSelect from './Boards/BoardAutoAddSelect';
|
||||
|
||||
const selector = createMemoizedSelector(selectGallerySlice, (gallery) => {
|
||||
const { galleryImageMinimumWidth, shouldAutoSwitch, autoAssignBoardOnClick } =
|
||||
gallery;
|
||||
|
||||
return {
|
||||
galleryImageMinimumWidth,
|
||||
shouldAutoSwitch,
|
||||
autoAssignBoardOnClick,
|
||||
};
|
||||
});
|
||||
|
||||
const GallerySettingsPopover = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { galleryImageMinimumWidth, shouldAutoSwitch, autoAssignBoardOnClick } =
|
||||
useAppSelector(selector);
|
||||
const galleryImageMinimumWidth = useAppSelector(
|
||||
(s) => s.gallery.galleryImageMinimumWidth
|
||||
);
|
||||
const shouldAutoSwitch = useAppSelector((s) => s.gallery.shouldAutoSwitch);
|
||||
const autoAssignBoardOnClick = useAppSelector(
|
||||
(s) => s.gallery.autoAssignBoardOnClick
|
||||
);
|
||||
|
||||
const handleChangeGalleryImageMinimumWidth = useCallback(
|
||||
(v: number) => {
|
||||
|
@ -1,39 +1,21 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import { selectHrfSlice, setHrfStrength } from 'features/hrf/store/hrfSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { setHrfStrength } from 'features/hrf/store/hrfSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectHrfSlice,
|
||||
selectConfigSlice,
|
||||
(hrf, config) => {
|
||||
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
||||
config.sd.hrfStrength;
|
||||
const { hrfStrength } = hrf;
|
||||
|
||||
return {
|
||||
hrfStrength,
|
||||
initial,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
step: coarseStep,
|
||||
fineStep,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamHrfStrength = () => {
|
||||
const { hrfStrength, initial, min, sliderMax, step, fineStep } =
|
||||
useAppSelector(selector);
|
||||
const hrfStrength = useAppSelector((s) => s.hrf.hrfStrength);
|
||||
const initial = useAppSelector((s) => s.config.sd.hrfStrength.initial);
|
||||
const min = useAppSelector((s) => s.config.sd.hrfStrength.min);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.hrfStrength.sliderMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.hrfStrength.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.hrfStrength.fineStep);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleHrfStrengthChange = useCallback(
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
dispatch(setHrfStrength(v));
|
||||
},
|
||||
@ -45,11 +27,11 @@ const ParamHrfStrength = () => {
|
||||
<InvSlider
|
||||
min={min}
|
||||
max={sliderMax}
|
||||
step={step}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
value={hrfStrength}
|
||||
defaultValue={initial}
|
||||
onChange={handleHrfStrengthChange}
|
||||
onChange={onChange}
|
||||
marks
|
||||
withNumberInput
|
||||
/>
|
||||
|
@ -6,12 +6,12 @@ import { selectLoraSlice } from 'features/lora/store/loraSlice';
|
||||
import { map } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
|
||||
const selector = createMemoizedSelector(selectLoraSlice, (lora) => {
|
||||
return { lorasArray: map(lora.loras) };
|
||||
});
|
||||
const selectLoRAsArray = createMemoizedSelector(selectLoraSlice, (lora) =>
|
||||
map(lora.loras)
|
||||
);
|
||||
|
||||
export const LoRAList = memo(() => {
|
||||
const { lorasArray } = useAppSelector(selector);
|
||||
const lorasArray = useAppSelector(selectLoRAsArray);
|
||||
|
||||
if (!lorasArray.length) {
|
||||
return null;
|
||||
|
@ -10,15 +10,16 @@ import { useTranslation } from 'react-i18next';
|
||||
import type { LoRAModelConfigEntity } from 'services/api/endpoints/models';
|
||||
import { useGetLoRAModelsQuery } from 'services/api/endpoints/models';
|
||||
|
||||
const selector = createMemoizedSelector(selectLoraSlice, (lora) => ({
|
||||
addedLoRAs: lora.loras,
|
||||
}));
|
||||
const selectAddedLoRAs = createMemoizedSelector(
|
||||
selectLoraSlice,
|
||||
(lora) => lora.loras
|
||||
);
|
||||
|
||||
const LoRASelect = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { data, isLoading } = useGetLoRAModelsQuery();
|
||||
const { t } = useTranslation();
|
||||
const { addedLoRAs } = useAppSelector(selector);
|
||||
const addedLoRAs = useAppSelector(selectAddedLoRAs);
|
||||
const currentBaseModel = useAppSelector(
|
||||
(s) => s.generation.model?.base_model
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { colorTokenToCssVar } from 'common/util/colorTokenToCssVar';
|
||||
import { getFieldColor } from 'features/nodes/components/flow/edges/util/getEdgeColor';
|
||||
@ -8,25 +8,17 @@ import { memo } from 'react';
|
||||
import type { ConnectionLineComponentProps } from 'reactflow';
|
||||
import { getBezierPath } from 'reactflow';
|
||||
|
||||
const selector = createMemoizedSelector(selectNodesSlice, (nodes) => {
|
||||
const { shouldAnimateEdges, connectionStartFieldType, shouldColorEdges } =
|
||||
nodes;
|
||||
const selectStroke = createSelector(selectNodesSlice, (nodes) =>
|
||||
nodes.shouldColorEdges
|
||||
? getFieldColor(nodes.connectionStartFieldType)
|
||||
: colorTokenToCssVar('base.500')
|
||||
);
|
||||
|
||||
const stroke = shouldColorEdges
|
||||
? getFieldColor(connectionStartFieldType)
|
||||
: colorTokenToCssVar('base.500');
|
||||
|
||||
let className = 'react-flow__custom_connection-path';
|
||||
|
||||
if (shouldAnimateEdges) {
|
||||
className = className.concat(' animated');
|
||||
}
|
||||
|
||||
return {
|
||||
stroke,
|
||||
className,
|
||||
};
|
||||
});
|
||||
const selectClassName = createSelector(selectNodesSlice, (nodes) =>
|
||||
nodes.shouldAnimateEdges
|
||||
? 'react-flow__custom_connection-path animated'
|
||||
: 'react-flow__custom_connection-path'
|
||||
);
|
||||
|
||||
const pathStyles: CSSProperties = { opacity: 0.8 };
|
||||
|
||||
@ -38,7 +30,8 @@ const CustomConnectionLine = ({
|
||||
toY,
|
||||
toPosition,
|
||||
}: ConnectionLineComponentProps) => {
|
||||
const { stroke, className } = useAppSelector(selector);
|
||||
const stroke = useAppSelector(selectStroke);
|
||||
const className = useAppSelector(selectClassName);
|
||||
|
||||
const pathParams = {
|
||||
sourceX: fromX,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import InvocationNode from 'features/nodes/components/flow/nodes/Invocation/InvocationNode';
|
||||
import { selectNodeTemplatesSlice } from 'features/nodes/store/nodeTemplatesSlice';
|
||||
@ -14,15 +14,15 @@ const InvocationNodeWrapper = (props: NodeProps<InvocationNodeData>) => {
|
||||
|
||||
const hasTemplateSelector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodeTemplatesSlice, (nodeTemplates) =>
|
||||
createSelector(selectNodeTemplatesSlice, (nodeTemplates) =>
|
||||
Boolean(nodeTemplates.templates[type])
|
||||
),
|
||||
[type]
|
||||
);
|
||||
|
||||
const nodeTemplate = useAppSelector(hasTemplateSelector);
|
||||
const hasTemplate = useAppSelector(hasTemplateSelector);
|
||||
|
||||
if (!nodeTemplate) {
|
||||
if (!hasTemplate) {
|
||||
return (
|
||||
<InvocationNodeUnknownFallback
|
||||
nodeId={nodeId}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import type { InvContextMenuProps } from 'common/components/InvContextMenu/InvContextMenu';
|
||||
import { InvContextMenu } from 'common/components/InvContextMenu/InvContextMenu';
|
||||
@ -36,16 +36,14 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
||||
e.preventDefault();
|
||||
}, []);
|
||||
|
||||
const selector = useMemo(
|
||||
const selectIsExposed = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectWorkflowSlice, (workflow) => {
|
||||
const isExposed = Boolean(
|
||||
createSelector(selectWorkflowSlice, (workflow) => {
|
||||
return Boolean(
|
||||
workflow.exposedFields.find(
|
||||
(f) => f.nodeId === nodeId && f.fieldName === fieldName
|
||||
)
|
||||
);
|
||||
|
||||
return { isExposed };
|
||||
}),
|
||||
[fieldName, nodeId]
|
||||
);
|
||||
@ -55,7 +53,7 @@ const FieldContextMenu = ({ nodeId, fieldName, kind, children }: Props) => {
|
||||
[input]
|
||||
);
|
||||
|
||||
const { isExposed } = useAppSelector(selector);
|
||||
const isExposed = useAppSelector(selectIsExposed);
|
||||
|
||||
const handleExposeField = useCallback(() => {
|
||||
dispatch(workflowExposedFieldAdded({ nodeId, fieldName }));
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { ChakraProps } from '@chakra-ui/react';
|
||||
import { Box, useToken } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import NodeSelectionOverlay from 'common/components/NodeSelectionOverlay';
|
||||
import { useGlobalMenuCloseTrigger } from 'common/hooks/useGlobalMenuCloseTrigger';
|
||||
@ -30,7 +30,7 @@ const NodeWrapper = (props: NodeWrapperProps) => {
|
||||
|
||||
const selectIsInProgress = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectNodesSlice,
|
||||
(nodes) =>
|
||||
nodes.nodeExecutionStates[nodeId]?.status ===
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { makeConnectionErrorSelector } from 'features/nodes/store/util/makeIsConnectionValidSelector';
|
||||
@ -6,7 +6,7 @@ import { useMemo } from 'react';
|
||||
|
||||
import { useFieldType } from './useFieldType.ts';
|
||||
|
||||
const selectIsConnectionInProgress = createMemoizedSelector(
|
||||
const selectIsConnectionInProgress = createSelector(
|
||||
selectNodesSlice,
|
||||
(nodes) =>
|
||||
nodes.connectionStartFieldType !== null &&
|
||||
@ -28,7 +28,7 @@ export const useConnectionState = ({
|
||||
|
||||
const selectIsConnected = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) =>
|
||||
createSelector(selectNodesSlice, (nodes) =>
|
||||
Boolean(
|
||||
nodes.edges.filter((edge) => {
|
||||
return (
|
||||
@ -55,7 +55,7 @@ export const useConnectionState = ({
|
||||
|
||||
const selectIsConnectionStartField = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) =>
|
||||
createSelector(selectNodesSlice, (nodes) =>
|
||||
Boolean(
|
||||
nodes.connectionStartParams?.nodeId === nodeId &&
|
||||
nodes.connectionStartParams?.handleId === fieldName &&
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { compareVersions } from 'compare-versions';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
@ -9,7 +9,7 @@ import { useMemo } from 'react';
|
||||
export const useDoNodeVersionsMatch = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectNodesSlice,
|
||||
selectNodeTemplatesSlice,
|
||||
(nodes, nodeTemplates) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { selectNodeTemplatesSlice } from 'features/nodes/store/nodeTemplatesSlice';
|
||||
@ -8,7 +8,7 @@ import { useMemo } from 'react';
|
||||
export const useFieldInputKind = (nodeId: string, fieldName: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectNodesSlice,
|
||||
selectNodeTemplatesSlice,
|
||||
(nodes, nodeTemplates) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
@ -7,7 +7,7 @@ import { useMemo } from 'react';
|
||||
export const useFieldLabel = (nodeId: string, fieldName: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) => {
|
||||
createSelector(selectNodesSlice, (nodes) => {
|
||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||
if (!isInvocationNode(node)) {
|
||||
return;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { selectNodeTemplatesSlice } from 'features/nodes/store/nodeTemplatesSlice';
|
||||
@ -13,7 +13,7 @@ export const useFieldTemplateTitle = (
|
||||
) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectNodesSlice,
|
||||
selectNodeTemplatesSlice,
|
||||
(nodes, nodeTemplates) => {
|
||||
@ -28,7 +28,7 @@ export const useFieldTemplateTitle = (
|
||||
[fieldName, kind, nodeId]
|
||||
);
|
||||
|
||||
const fieldTemplate = useAppSelector(selector);
|
||||
const fieldTemplateTitle = useAppSelector(selector);
|
||||
|
||||
return fieldTemplate;
|
||||
return fieldTemplateTitle;
|
||||
};
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { selectNodeTemplatesSlice } from 'features/nodes/store/nodeTemplatesSlice';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
import { getNeedsUpdate } from 'features/nodes/util/node/nodeUpdate';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selector = createSelector(
|
||||
selectNodesSlice,
|
||||
selectNodeTemplatesSlice,
|
||||
(nodes, nodeTemplates) =>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
@ -7,7 +7,7 @@ import { useMemo } from 'react';
|
||||
export const useIsIntermediate = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) => {
|
||||
createSelector(selectNodesSlice, (nodes) => {
|
||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||
if (!isInvocationNode(node)) {
|
||||
return false;
|
||||
@ -17,6 +17,6 @@ export const useIsIntermediate = (nodeId: string) => {
|
||||
[nodeId]
|
||||
);
|
||||
|
||||
const is_intermediate = useAppSelector(selector);
|
||||
return is_intermediate;
|
||||
const isIntermediate = useAppSelector(selector);
|
||||
return isIntermediate;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
@ -7,7 +7,7 @@ import { useMemo } from 'react';
|
||||
export const useNodeLabel = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) => {
|
||||
createSelector(selectNodesSlice, (nodes) => {
|
||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||
if (!isInvocationNode(node)) {
|
||||
return false;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
@ -7,7 +7,7 @@ import { useMemo } from 'react';
|
||||
export const useNodePack = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) => {
|
||||
createSelector(selectNodesSlice, (nodes) => {
|
||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||
if (!isInvocationNode(node)) {
|
||||
return false;
|
||||
@ -17,6 +17,6 @@ export const useNodePack = (nodeId: string) => {
|
||||
[nodeId]
|
||||
);
|
||||
|
||||
const title = useAppSelector(selector);
|
||||
return title;
|
||||
const nodePack = useAppSelector(selector);
|
||||
return nodePack;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { selectNodeTemplatesSlice } from 'features/nodes/store/nodeTemplatesSlice';
|
||||
@ -8,7 +8,7 @@ import { useMemo } from 'react';
|
||||
export const useNodeTemplateTitle = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(
|
||||
createSelector(
|
||||
selectNodesSlice,
|
||||
selectNodeTemplatesSlice,
|
||||
(nodes, nodeTemplates) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import { isInvocationNode } from 'features/nodes/types/invocation';
|
||||
@ -7,13 +7,11 @@ import { useMemo } from 'react';
|
||||
export const useUseCache = (nodeId: string) => {
|
||||
const selector = useMemo(
|
||||
() =>
|
||||
createMemoizedSelector(selectNodesSlice, (nodes) => {
|
||||
createSelector(selectNodesSlice, (nodes) => {
|
||||
const node = nodes.nodes.find((node) => node.id === nodeId);
|
||||
if (!isInvocationNode(node)) {
|
||||
return false;
|
||||
}
|
||||
// cast to boolean to support older workflows that didn't have useCache
|
||||
// TODO: handle this better somehow
|
||||
return node.data.useCache;
|
||||
}),
|
||||
[nodeId]
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { selectNodesSlice } from 'features/nodes/store/nodesSlice';
|
||||
import type { FieldType } from 'features/nodes/types/field';
|
||||
import i18n from 'i18next';
|
||||
@ -18,7 +18,7 @@ export const makeConnectionErrorSelector = (
|
||||
handleType: HandleType,
|
||||
fieldType?: FieldType
|
||||
) => {
|
||||
return createMemoizedSelector(selectNodesSlice, (nodesSlice) => {
|
||||
return createSelector(selectNodesSlice, (nodesSlice) => {
|
||||
if (!fieldType) {
|
||||
return i18n.t('nodes.noFieldType');
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
@ -12,18 +11,9 @@ import { selectOptimalDimension } from 'features/parameters/store/generationSlic
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectOptimalDimension, isStagingSelector],
|
||||
(optimalDimension, isStaging) => {
|
||||
return {
|
||||
initial: optimalDimension,
|
||||
isStaging,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamBoundingBoxWidth = () => {
|
||||
const { isStaging, initial } = useAppSelector(selector);
|
||||
const isStaging = useAppSelector(isStagingSelector);
|
||||
const initial = useAppSelector(selectOptimalDimension);
|
||||
const ctx = useImageSizeContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
@ -12,18 +11,9 @@ import { selectOptimalDimension } from 'features/parameters/store/generationSlic
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectOptimalDimension, isStagingSelector],
|
||||
(optimalDimension, isStaging) => {
|
||||
return {
|
||||
initial: optimalDimension,
|
||||
isStaging,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamBoundingBoxWidth = () => {
|
||||
const { isStaging, initial } = useAppSelector(selector);
|
||||
const isStaging = useAppSelector(isStagingSelector);
|
||||
const initial = useAppSelector(selectOptimalDimension);
|
||||
const ctx = useImageSizeContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
@ -1,11 +1,7 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import {
|
||||
selectCanvasSlice,
|
||||
setScaledBoundingBoxDimensions,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
|
||||
import {
|
||||
CANVAS_GRID_SIZE_COARSE,
|
||||
CANVAS_GRID_SIZE_FINE,
|
||||
@ -14,34 +10,26 @@ import { selectOptimalDimension } from 'features/parameters/store/generationSlic
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectCanvasSlice, selectOptimalDimension],
|
||||
(canvas, optimalDimension) => {
|
||||
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = canvas;
|
||||
|
||||
return {
|
||||
optimalDimension,
|
||||
scaledBoundingBoxDimensions,
|
||||
isManual: boundingBoxScaleMethod === 'manual',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamScaledHeight = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { isManual, scaledBoundingBoxDimensions, optimalDimension } =
|
||||
useAppSelector(selector);
|
||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||
const isManual = useAppSelector(
|
||||
(s) => s.canvas.boundingBoxScaleMethod === 'manual'
|
||||
);
|
||||
const height = useAppSelector(
|
||||
(s) => s.canvas.scaledBoundingBoxDimensions.height
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChangeScaledHeight = useCallback(
|
||||
const onChange = useCallback(
|
||||
(height: number) => {
|
||||
dispatch(setScaledBoundingBoxDimensions({ height }));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const handleResetScaledHeight = useCallback(() => {
|
||||
const onReset = useCallback(() => {
|
||||
dispatch(setScaledBoundingBoxDimensions({ height: optimalDimension }));
|
||||
}, [dispatch, optimalDimension]);
|
||||
|
||||
@ -52,12 +40,12 @@ const ParamScaledHeight = () => {
|
||||
max={1536}
|
||||
step={CANVAS_GRID_SIZE_COARSE}
|
||||
fineStep={CANVAS_GRID_SIZE_FINE}
|
||||
value={scaledBoundingBoxDimensions.height}
|
||||
onChange={handleChangeScaledHeight}
|
||||
value={height}
|
||||
onChange={onChange}
|
||||
marks
|
||||
withNumberInput
|
||||
numberInputMax={4096}
|
||||
onReset={handleResetScaledHeight}
|
||||
onReset={onReset}
|
||||
/>
|
||||
</InvControl>
|
||||
);
|
||||
|
@ -1,11 +1,7 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import {
|
||||
selectCanvasSlice,
|
||||
setScaledBoundingBoxDimensions,
|
||||
} from 'features/canvas/store/canvasSlice';
|
||||
import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
|
||||
import {
|
||||
CANVAS_GRID_SIZE_COARSE,
|
||||
CANVAS_GRID_SIZE_FINE,
|
||||
@ -14,34 +10,25 @@ import { selectOptimalDimension } from 'features/parameters/store/generationSlic
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectCanvasSlice, selectOptimalDimension],
|
||||
(canvas, optimalDimension) => {
|
||||
const { boundingBoxScaleMethod, scaledBoundingBoxDimensions } = canvas;
|
||||
|
||||
return {
|
||||
optimalDimension,
|
||||
scaledBoundingBoxDimensions,
|
||||
isManual: boundingBoxScaleMethod === 'manual',
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamScaledWidth = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { optimalDimension, isManual, scaledBoundingBoxDimensions } =
|
||||
useAppSelector(selector);
|
||||
|
||||
const { t } = useTranslation();
|
||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||
const isManual = useAppSelector(
|
||||
(s) => s.canvas.boundingBoxScaleMethod === 'manual'
|
||||
);
|
||||
const width = useAppSelector(
|
||||
(s) => s.canvas.scaledBoundingBoxDimensions.width
|
||||
);
|
||||
|
||||
const handleChangeScaledWidth = useCallback(
|
||||
const onChange = useCallback(
|
||||
(width: number) => {
|
||||
dispatch(setScaledBoundingBoxDimensions({ width }));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const handleResetScaledWidth = useCallback(() => {
|
||||
const onReset = useCallback(() => {
|
||||
dispatch(setScaledBoundingBoxDimensions({ width: optimalDimension }));
|
||||
}, [dispatch, optimalDimension]);
|
||||
|
||||
@ -52,12 +39,12 @@ const ParamScaledWidth = () => {
|
||||
max={1536}
|
||||
step={CANVAS_GRID_SIZE_COARSE}
|
||||
fineStep={CANVAS_GRID_SIZE_FINE}
|
||||
value={scaledBoundingBoxDimensions.width}
|
||||
onChange={handleChangeScaledWidth}
|
||||
value={width}
|
||||
onChange={onChange}
|
||||
numberInputMax={4096}
|
||||
marks
|
||||
withNumberInput
|
||||
onReset={handleResetScaledWidth}
|
||||
onReset={onReset}
|
||||
/>
|
||||
</InvControl>
|
||||
);
|
||||
|
@ -1,50 +1,24 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import {
|
||||
selectGenerationSlice,
|
||||
setCfgScale,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { setCfgScale } from 'features/parameters/store/generationSlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
selectConfigSlice,
|
||||
(generation, config) => {
|
||||
const { min, inputMax, sliderMax, coarseStep, fineStep, initial } =
|
||||
config.sd.guidance;
|
||||
const { cfgScale } = generation;
|
||||
|
||||
return {
|
||||
marks: [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
cfgScale,
|
||||
min,
|
||||
inputMax,
|
||||
sliderMax,
|
||||
coarseStep,
|
||||
fineStep,
|
||||
initial,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamCFGScale = () => {
|
||||
const {
|
||||
cfgScale,
|
||||
min,
|
||||
inputMax,
|
||||
sliderMax,
|
||||
coarseStep,
|
||||
fineStep,
|
||||
initial,
|
||||
marks,
|
||||
} = useAppSelector(selector);
|
||||
const cfgScale = useAppSelector((s) => s.generation.cfgScale);
|
||||
const min = useAppSelector((s) => s.config.sd.guidance.min);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.guidance.inputMax);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.guidance.sliderMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.guidance.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.guidance.fineStep);
|
||||
const initial = useAppSelector((s) => s.config.sd.guidance.initial);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const marks = useMemo(
|
||||
() => [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
[sliderMax, min]
|
||||
);
|
||||
const onChange = useCallback(
|
||||
(v: number) => dispatch(setCfgScale(v)),
|
||||
[dispatch]
|
||||
|
@ -1,35 +1,21 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvNumberInput } from 'common/components/InvNumberInput/InvNumberInput';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import { useImageSizeContext } from 'features/parameters/components/ImageSize/ImageSizeContext';
|
||||
import { selectOptimalDimension } from 'features/parameters/store/generationSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectConfigSlice, selectOptimalDimension],
|
||||
(config, optimalDimension) => {
|
||||
const { min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.height;
|
||||
|
||||
return {
|
||||
initial: optimalDimension,
|
||||
min,
|
||||
max: sliderMax,
|
||||
inputMax,
|
||||
step: coarseStep,
|
||||
fineStep,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export const ParamHeight = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const ctx = useImageSizeContext();
|
||||
const { initial, min, max, inputMax, step, fineStep } =
|
||||
useAppSelector(selector);
|
||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||
const min = useAppSelector((s) => s.config.sd.height.min);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.height.sliderMax);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.height.inputMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.height.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.height.fineStep);
|
||||
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
@ -38,17 +24,20 @@ export const ParamHeight = memo(() => {
|
||||
[ctx]
|
||||
);
|
||||
|
||||
const marks = useMemo(() => [min, initial, max], [min, initial, max]);
|
||||
const marks = useMemo(
|
||||
() => [min, optimalDimension, sliderMax],
|
||||
[min, optimalDimension, sliderMax]
|
||||
);
|
||||
|
||||
return (
|
||||
<InvControl label={t('parameters.height')}>
|
||||
<InvSlider
|
||||
value={ctx.height}
|
||||
defaultValue={initial}
|
||||
defaultValue={optimalDimension}
|
||||
onChange={onChange}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
max={sliderMax}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
marks={marks}
|
||||
/>
|
||||
@ -57,9 +46,9 @@ export const ParamHeight = memo(() => {
|
||||
onChange={onChange}
|
||||
min={min}
|
||||
max={inputMax}
|
||||
step={step}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
defaultValue={initial}
|
||||
defaultValue={optimalDimension}
|
||||
/>
|
||||
</InvControl>
|
||||
);
|
||||
|
@ -1,43 +1,27 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import {
|
||||
clampSymmetrySteps,
|
||||
selectGenerationSlice,
|
||||
setSteps,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
selectConfigSlice,
|
||||
(generation, config) => {
|
||||
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
||||
config.sd.steps;
|
||||
const { steps } = generation;
|
||||
|
||||
return {
|
||||
marks: [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
steps,
|
||||
initial,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
step: coarseStep,
|
||||
fineStep,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const ParamSteps = () => {
|
||||
const { steps, initial, min, sliderMax, inputMax, step, fineStep, marks } =
|
||||
useAppSelector(selector);
|
||||
const steps = useAppSelector((s) => s.generation.steps);
|
||||
const initial = useAppSelector((s) => s.config.sd.steps.initial);
|
||||
const min = useAppSelector((s) => s.config.sd.steps.min);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.steps.sliderMax);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.steps.inputMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.steps.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.steps.fineStep);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const marks = useMemo(
|
||||
() => [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
[sliderMax, min]
|
||||
);
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
dispatch(setSteps(v));
|
||||
@ -56,7 +40,7 @@ const ParamSteps = () => {
|
||||
defaultValue={initial}
|
||||
min={min}
|
||||
max={sliderMax}
|
||||
step={step}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
|
@ -1,34 +1,21 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvNumberInput } from 'common/components/InvNumberInput/InvNumberInput';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import { useImageSizeContext } from 'features/parameters/components/ImageSize/ImageSizeContext';
|
||||
import { selectOptimalDimension } from 'features/parameters/store/generationSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
[selectConfigSlice, selectOptimalDimension],
|
||||
(config, optimalDimension) => {
|
||||
const { min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.width;
|
||||
|
||||
return {
|
||||
initial: optimalDimension,
|
||||
min,
|
||||
max: sliderMax,
|
||||
step: coarseStep,
|
||||
inputMax,
|
||||
fineStep,
|
||||
};
|
||||
}
|
||||
);
|
||||
export const ParamWidth = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const ctx = useImageSizeContext();
|
||||
const { initial, min, max, inputMax, step, fineStep } =
|
||||
useAppSelector(selector);
|
||||
const optimalDimension = useAppSelector(selectOptimalDimension);
|
||||
const min = useAppSelector((s) => s.config.sd.width.min);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.width.sliderMax);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.width.inputMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.width.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.width.fineStep);
|
||||
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
@ -37,17 +24,20 @@ export const ParamWidth = memo(() => {
|
||||
[ctx]
|
||||
);
|
||||
|
||||
const marks = useMemo(() => [min, initial, max], [min, initial, max]);
|
||||
const marks = useMemo(
|
||||
() => [min, optimalDimension, sliderMax],
|
||||
[min, optimalDimension, sliderMax]
|
||||
);
|
||||
|
||||
return (
|
||||
<InvControl label={t('parameters.width')}>
|
||||
<InvSlider
|
||||
value={ctx.width}
|
||||
onChange={onChange}
|
||||
defaultValue={initial}
|
||||
defaultValue={optimalDimension}
|
||||
min={min}
|
||||
max={max}
|
||||
step={step}
|
||||
max={sliderMax}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
marks={marks}
|
||||
/>
|
||||
@ -56,9 +46,9 @@ export const ParamWidth = memo(() => {
|
||||
onChange={onChange}
|
||||
min={min}
|
||||
max={inputMax}
|
||||
step={step}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
defaultValue={initial}
|
||||
defaultValue={optimalDimension}
|
||||
/>
|
||||
</InvControl>
|
||||
);
|
||||
|
@ -1,40 +1,24 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import {
|
||||
selectGenerationSlice,
|
||||
setImg2imgStrength,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { setImg2imgStrength } from 'features/parameters/store/generationSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
selectConfigSlice,
|
||||
(generation, config) => {
|
||||
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
||||
config.sd.img2imgStrength;
|
||||
const { img2imgStrength } = generation;
|
||||
|
||||
return {
|
||||
img2imgStrength,
|
||||
initial,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
step: coarseStep,
|
||||
fineStep,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const marks = [0, 0.5, 1];
|
||||
|
||||
const ImageToImageStrength = () => {
|
||||
const { img2imgStrength, initial, min, sliderMax, inputMax, step, fineStep } =
|
||||
useAppSelector(selector);
|
||||
const img2imgStrength = useAppSelector((s) => s.generation.img2imgStrength);
|
||||
const initial = useAppSelector((s) => s.config.sd.img2imgStrength.initial);
|
||||
const min = useAppSelector((s) => s.config.sd.img2imgStrength.min);
|
||||
const sliderMax = useAppSelector(
|
||||
(s) => s.config.sd.img2imgStrength.sliderMax
|
||||
);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.img2imgStrength.inputMax);
|
||||
const coarseStep = useAppSelector(
|
||||
(s) => s.config.sd.img2imgStrength.coarseStep
|
||||
);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.img2imgStrength.fineStep);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -49,7 +33,7 @@ const ImageToImageStrength = () => {
|
||||
feature="paramDenoisingStrength"
|
||||
>
|
||||
<InvSlider
|
||||
step={step}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
min={min}
|
||||
max={sliderMax}
|
||||
|
@ -11,28 +11,18 @@ import {
|
||||
clearInitialImage,
|
||||
selectGenerationSlice,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { selectSystemSlice } from 'features/system/store/systemSlice';
|
||||
import { memo, useEffect, useMemo } from 'react';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selectInitialImage = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
selectSystemSlice,
|
||||
(generation, system) => {
|
||||
const { initialImage } = generation;
|
||||
const { isConnected } = system;
|
||||
|
||||
return {
|
||||
initialImage,
|
||||
isResetButtonDisabled: !initialImage,
|
||||
isConnected,
|
||||
};
|
||||
}
|
||||
(generation) => generation.initialImage
|
||||
);
|
||||
|
||||
const InitialImage = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { initialImage, isConnected } = useAppSelector(selector);
|
||||
const initialImage = useAppSelector(selectInitialImage);
|
||||
const isConnected = useAppSelector((s) => s.system.isConnected);
|
||||
|
||||
const { currentData: imageDTO, isError } = useGetImageDTOQuery(
|
||||
initialImage?.imageName ?? skipToken
|
||||
|
@ -17,13 +17,10 @@ import type { PostUploadAction } from 'services/api/types';
|
||||
|
||||
import InitialImage from './InitialImage';
|
||||
|
||||
const selector = createMemoizedSelector(selectGenerationSlice, (generation) => {
|
||||
const { initialImage } = generation;
|
||||
return {
|
||||
isResetButtonDisabled: !initialImage,
|
||||
initialImage,
|
||||
};
|
||||
});
|
||||
const selectInitialImage = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
(generation) => generation.initialImage
|
||||
);
|
||||
|
||||
const postUploadAction: PostUploadAction = {
|
||||
type: 'SET_INITIAL_IMAGE',
|
||||
@ -32,7 +29,7 @@ const postUploadAction: PostUploadAction = {
|
||||
const InitialImageDisplay = () => {
|
||||
const { recallWidthAndHeight } = useRecallParameters();
|
||||
const { t } = useTranslation();
|
||||
const { isResetButtonDisabled, initialImage } = useAppSelector(selector);
|
||||
const initialImage = useAppSelector(selectInitialImage);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({
|
||||
@ -91,14 +88,14 @@ const InitialImageDisplay = () => {
|
||||
aria-label={`${t('parameters.useSize')} (Shift+D)`}
|
||||
icon={<FaRulerVertical />}
|
||||
onClick={handleUseSizeInitialImage}
|
||||
isDisabled={isResetButtonDisabled}
|
||||
isDisabled={!initialImage}
|
||||
/>
|
||||
<InvIconButton
|
||||
tooltip="Reset Initial Image"
|
||||
aria-label="Reset Initial Image"
|
||||
icon={<FaUndo />}
|
||||
onClick={handleReset}
|
||||
isDisabled={isResetButtonDisabled}
|
||||
isDisabled={!initialImage}
|
||||
/>
|
||||
</Flex>
|
||||
<InitialImage />
|
||||
|
@ -12,17 +12,15 @@ import { NON_REFINER_BASE_MODELS } from 'services/api/constants';
|
||||
import type { MainModelConfigEntity } from 'services/api/endpoints/models';
|
||||
import { useGetMainModelsQuery } from 'services/api/endpoints/models';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selectModel = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
(generation) => ({
|
||||
model: generation.model,
|
||||
})
|
||||
(generation) => generation.model
|
||||
);
|
||||
|
||||
const ParamMainModelSelect = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const { model } = useAppSelector(selector);
|
||||
const model = useAppSelector(selectModel);
|
||||
const { data, isLoading } = useGetMainModelsQuery(NON_REFINER_BASE_MODELS);
|
||||
const _onChange = useCallback(
|
||||
(model: MainModelConfigEntity | null) => {
|
||||
|
@ -23,11 +23,14 @@ const ParamVAEModelSelect = () => {
|
||||
const { t } = useTranslation();
|
||||
const { model, vae } = useAppSelector(selector);
|
||||
const { data, isLoading } = useGetVaeModelsQuery();
|
||||
const getIsDisabled = (vae: VaeModelConfigEntity): boolean => {
|
||||
const isCompatible = model?.base_model === vae.base_model;
|
||||
const hasMainModel = Boolean(model?.base_model);
|
||||
return !hasMainModel || !isCompatible;
|
||||
};
|
||||
const getIsDisabled = useCallback(
|
||||
(vae: VaeModelConfigEntity): boolean => {
|
||||
const isCompatible = model?.base_model === vae.base_model;
|
||||
const hasMainModel = Boolean(model?.base_model);
|
||||
return !hasMainModel || !isCompatible;
|
||||
},
|
||||
[model?.base_model]
|
||||
);
|
||||
const _onChange = useCallback(
|
||||
(vae: VaeModelConfigEntity | null) => {
|
||||
dispatch(vaeSelected(vae ? pick(vae, 'base_model', 'model_name') : null));
|
||||
|
@ -99,7 +99,7 @@ import {
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
const selectModel = createMemoizedSelector(
|
||||
selectGenerationSlice,
|
||||
(generation) => generation.model
|
||||
);
|
||||
@ -108,7 +108,7 @@ export const useRecallParameters = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const toaster = useAppToaster();
|
||||
const { t } = useTranslation();
|
||||
const model = useAppSelector(selector);
|
||||
const model = useAppSelector(selectModel);
|
||||
|
||||
const parameterSetToast = useCallback(() => {
|
||||
toaster({
|
||||
|
@ -1,89 +1,24 @@
|
||||
import { Flex, Spacer } from '@chakra-ui/layout';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIInformationalPopover from 'common/components/IAIInformationalPopover/IAIInformationalPopover';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvButton } from 'common/components/InvButton/InvButton';
|
||||
import { InvNumberInput } from 'common/components/InvNumberInput/InvNumberInput';
|
||||
import type { InvNumberInputFieldProps } from 'common/components/InvNumberInput/types';
|
||||
import { selectDynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import {
|
||||
selectGenerationSlice,
|
||||
setIterations,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { QueueIterationsNumberInput } from 'features/queue/components/QueueIterationsNumberInput';
|
||||
import { useQueueBack } from 'features/queue/hooks/useQueueBack';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { memo } from 'react';
|
||||
import { IoSparkles } from 'react-icons/io5';
|
||||
|
||||
import { QueueButtonTooltip } from './QueueButtonTooltip';
|
||||
|
||||
const invoke = 'Invoke';
|
||||
|
||||
const numberInputFieldProps: InvNumberInputFieldProps = {
|
||||
ps: 6,
|
||||
borderInlineStartRadius: 'base',
|
||||
h: 'full',
|
||||
textAlign: 'center',
|
||||
fontSize: 'md',
|
||||
fontWeight: 'semibold',
|
||||
};
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectConfigSlice,
|
||||
selectGenerationSlice,
|
||||
selectDynamicPromptsSlice,
|
||||
(config, generation, dynamicPrompts) => {
|
||||
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
||||
config.sd.iterations;
|
||||
const { iterations } = generation;
|
||||
const isLoadingDynamicPrompts = dynamicPrompts.isLoading;
|
||||
|
||||
return {
|
||||
iterations,
|
||||
initial,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
step: coarseStep,
|
||||
fineStep,
|
||||
isLoadingDynamicPrompts,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
export const InvokeQueueBackButton = memo(() => {
|
||||
const { queueBack, isLoading, isDisabled } = useQueueBack();
|
||||
const { iterations, step, fineStep, isLoadingDynamicPrompts } =
|
||||
useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
const handleChange = useCallback(
|
||||
(v: number) => {
|
||||
dispatch(setIterations(v));
|
||||
},
|
||||
[dispatch]
|
||||
const isLoadingDynamicPrompts = useAppSelector(
|
||||
(s) => s.dynamicPrompts.isLoading
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex pos="relative" flexGrow={1} minW="240px">
|
||||
<IAIInformationalPopover feature="paramIterations">
|
||||
<InvNumberInput
|
||||
step={step}
|
||||
fineStep={fineStep}
|
||||
min={1}
|
||||
max={999}
|
||||
onChange={handleChange}
|
||||
value={iterations}
|
||||
defaultValue={1}
|
||||
numberInputFieldProps={numberInputFieldProps}
|
||||
pos="absolute"
|
||||
insetInlineEnd={0}
|
||||
h="full"
|
||||
ps={0}
|
||||
w="72px"
|
||||
flexShrink={0}
|
||||
variant="darkFilled"
|
||||
/>
|
||||
</IAIInformationalPopover>
|
||||
<QueueIterationsNumberInput />
|
||||
<InvButton
|
||||
onClick={queueBack}
|
||||
isLoading={isLoading || isLoadingDynamicPrompts}
|
||||
|
@ -1,35 +1,23 @@
|
||||
import { Divider, Flex, ListItem, UnorderedList } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvText } from 'common/components/InvText/wrapper';
|
||||
import { useIsReadyToEnqueue } from 'common/hooks/useIsReadyToEnqueue';
|
||||
import { selectDynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
|
||||
import { getShouldProcessPrompt } from 'features/dynamicPrompts/util/getShouldProcessPrompt';
|
||||
import { selectGallerySlice } from 'features/gallery/store/gallerySlice';
|
||||
import { selectGenerationSlice } from 'features/parameters/store/generationSlice';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEnqueueBatchMutation } from 'services/api/endpoints/queue';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
|
||||
const StyledDivider = () => <Divider opacity={0.2} borderColor="base.900" />;
|
||||
|
||||
const tooltipSelector = createMemoizedSelector(
|
||||
selectGallerySlice,
|
||||
selectDynamicPromptsSlice,
|
||||
const selectPromptsCount = createSelector(
|
||||
selectGenerationSlice,
|
||||
(gallery, dynamicPrompts, generation) => {
|
||||
const { autoAddBoardId } = gallery;
|
||||
const { iterations, positivePrompt } = generation;
|
||||
const promptsCount = getShouldProcessPrompt(positivePrompt)
|
||||
selectDynamicPromptsSlice,
|
||||
(generation, dynamicPrompts) =>
|
||||
getShouldProcessPrompt(generation.positivePrompt)
|
||||
? dynamicPrompts.prompts.length
|
||||
: 1;
|
||||
return {
|
||||
autoAddBoardId,
|
||||
promptsCount,
|
||||
iterations,
|
||||
};
|
||||
}
|
||||
: 1
|
||||
);
|
||||
|
||||
type Props = {
|
||||
@ -42,8 +30,9 @@ export const QueueButtonTooltip = memo(({ prepend = false }: Props) => {
|
||||
const isLoadingDynamicPrompts = useAppSelector(
|
||||
(s) => s.dynamicPrompts.isLoading
|
||||
);
|
||||
const { autoAddBoardId, promptsCount, iterations } =
|
||||
useAppSelector(tooltipSelector);
|
||||
const promptsCount = useAppSelector(selectPromptsCount);
|
||||
const iterations = useAppSelector((s) => s.generation.iterations);
|
||||
const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId);
|
||||
const autoAddBoardName = useBoardName(autoAddBoardId);
|
||||
const [_, { isLoading }] = useEnqueueBatchMutation({
|
||||
fixedCacheKey: 'enqueueBatch',
|
||||
@ -77,7 +66,7 @@ export const QueueButtonTooltip = memo(({ prepend = false }: Props) => {
|
||||
</InvText>
|
||||
{reasons.length > 0 && (
|
||||
<>
|
||||
<StyledDivider />
|
||||
<Divider opacity={0.2} borderColor="base.900" />
|
||||
<UnorderedList>
|
||||
{reasons.map((reason, i) => (
|
||||
<ListItem key={`${reason}.${i}`}>
|
||||
@ -87,7 +76,7 @@ export const QueueButtonTooltip = memo(({ prepend = false }: Props) => {
|
||||
</UnorderedList>
|
||||
</>
|
||||
)}
|
||||
<StyledDivider />
|
||||
<Divider opacity={0.2} borderColor="base.900" />
|
||||
<InvText fontStyle="oblique 10deg">
|
||||
{t('parameters.invoke.addingImagesTo')}{' '}
|
||||
<InvText as="span" fontWeight="semibold">
|
||||
|
@ -0,0 +1,52 @@
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIInformationalPopover from 'common/components/IAIInformationalPopover/IAIInformationalPopover';
|
||||
import { InvNumberInput } from 'common/components/InvNumberInput/InvNumberInput';
|
||||
import type { InvNumberInputFieldProps } from 'common/components/InvNumberInput/types';
|
||||
import { setIterations } from 'features/parameters/store/generationSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
|
||||
const numberInputFieldProps: InvNumberInputFieldProps = {
|
||||
ps: 6,
|
||||
borderInlineStartRadius: 'base',
|
||||
h: 'full',
|
||||
textAlign: 'center',
|
||||
fontSize: 'md',
|
||||
fontWeight: 'semibold',
|
||||
};
|
||||
|
||||
export const QueueIterationsNumberInput = memo(() => {
|
||||
const iterations = useAppSelector((s) => s.generation.iterations);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.iterations.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.iterations.fineStep);
|
||||
const dispatch = useAppDispatch();
|
||||
const handleChange = useCallback(
|
||||
(v: number) => {
|
||||
dispatch(setIterations(v));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
return (
|
||||
<IAIInformationalPopover feature="paramIterations">
|
||||
<InvNumberInput
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
min={1}
|
||||
max={999}
|
||||
onChange={handleChange}
|
||||
value={iterations}
|
||||
defaultValue={1}
|
||||
numberInputFieldProps={numberInputFieldProps}
|
||||
pos="absolute"
|
||||
insetInlineEnd={0}
|
||||
h="full"
|
||||
ps={0}
|
||||
w="72px"
|
||||
flexShrink={0}
|
||||
variant="darkFilled"
|
||||
/>
|
||||
</IAIInformationalPopover>
|
||||
);
|
||||
});
|
||||
|
||||
QueueIterationsNumberInput.displayName = 'QueueIterationsNumberInput';
|
@ -1,33 +1,24 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import { setRefinerCFGScale } from 'features/sdxl/store/sdxlSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(selectConfigSlice, (config) => {
|
||||
const { min, inputMax, sliderMax, coarseStep, fineStep, initial } =
|
||||
config.sd.guidance;
|
||||
|
||||
return {
|
||||
marks: [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
min,
|
||||
inputMax,
|
||||
sliderMax,
|
||||
coarseStep,
|
||||
fineStep,
|
||||
initial,
|
||||
};
|
||||
});
|
||||
|
||||
const ParamSDXLRefinerCFGScale = () => {
|
||||
const refinerCFGScale = useAppSelector((s) => s.sdxl.refinerCFGScale);
|
||||
const { marks, min, inputMax, sliderMax, coarseStep, fineStep, initial } =
|
||||
useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const refinerCFGScale = useAppSelector((s) => s.sdxl.refinerCFGScale);
|
||||
const min = useAppSelector((s) => s.config.sd.guidance.min);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.guidance.inputMax);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.guidance.sliderMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.guidance.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.guidance.fineStep);
|
||||
const initial = useAppSelector((s) => s.config.sd.guidance.initial);
|
||||
const marks = useMemo(
|
||||
() => [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
[sliderMax, min]
|
||||
);
|
||||
|
||||
const onChange = useCallback(
|
||||
(v: number) => dispatch(setRefinerCFGScale(v)),
|
||||
|
@ -13,16 +13,17 @@ import { REFINER_BASE_MODELS } from 'services/api/constants';
|
||||
import type { MainModelConfigEntity } from 'services/api/endpoints/models';
|
||||
import { useGetMainModelsQuery } from 'services/api/endpoints/models';
|
||||
|
||||
const selector = createMemoizedSelector(selectSdxlSlice, (sdxl) => ({
|
||||
model: sdxl.refinerModel,
|
||||
}));
|
||||
const selectModel = createMemoizedSelector(
|
||||
selectSdxlSlice,
|
||||
(sdxl) => sdxl.refinerModel
|
||||
);
|
||||
|
||||
const optionsFilter = (model: MainModelConfigEntity) =>
|
||||
model.base_model === 'sdxl-refiner';
|
||||
|
||||
const ParamSDXLRefinerModelSelect = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { model } = useAppSelector(selector);
|
||||
const model = useAppSelector(selectModel);
|
||||
const { t } = useTranslation();
|
||||
const { data, isLoading } = useGetMainModelsQuery(REFINER_BASE_MODELS);
|
||||
const _onChange = useCallback(
|
||||
|
@ -1,32 +1,25 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSlider } from 'common/components/InvSlider/InvSlider';
|
||||
import { setRefinerSteps } from 'features/sdxl/store/sdxlSlice';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createMemoizedSelector(selectConfigSlice, (config) => {
|
||||
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
||||
config.sd.steps;
|
||||
|
||||
return {
|
||||
marks: [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
initial,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
step: coarseStep,
|
||||
fineStep,
|
||||
};
|
||||
});
|
||||
const ParamSDXLRefinerSteps = () => {
|
||||
const { initial, min, sliderMax, inputMax, step, fineStep, marks } =
|
||||
useAppSelector(selector);
|
||||
const refinerSteps = useAppSelector((s) => s.sdxl.refinerSteps);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
const refinerSteps = useAppSelector((s) => s.sdxl.refinerSteps);
|
||||
const initial = useAppSelector((s) => s.config.sd.steps.initial);
|
||||
const min = useAppSelector((s) => s.config.sd.steps.min);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.steps.sliderMax);
|
||||
const inputMax = useAppSelector((s) => s.config.sd.steps.inputMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.steps.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.steps.fineStep);
|
||||
|
||||
const marks = useMemo(
|
||||
() => [min, Math.floor(sliderMax / 2), sliderMax],
|
||||
[sliderMax, min]
|
||||
);
|
||||
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
@ -42,7 +35,7 @@ const ParamSDXLRefinerSteps = () => {
|
||||
defaultValue={initial}
|
||||
min={min}
|
||||
max={sliderMax}
|
||||
step={step}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
onChange={onChange}
|
||||
withNumberInput
|
||||
|
@ -61,8 +61,7 @@ const selector = createMemoizedSelector(
|
||||
isError = true;
|
||||
}
|
||||
|
||||
const controlAdapterIds =
|
||||
selectControlAdapterIds(controlAdapters).map(String);
|
||||
const controlAdapterIds = selectControlAdapterIds(controlAdapters);
|
||||
|
||||
return {
|
||||
controlAdapterIds,
|
||||
|
@ -26,16 +26,14 @@ const stepsScaleLabelProps: InvLabelProps = {
|
||||
minW: '5rem',
|
||||
};
|
||||
|
||||
const selector = createMemoizedSelector(selectSdxlSlice, (sdxl) => {
|
||||
return {
|
||||
badges: sdxl.refinerModel ? ['Enabled'] : undefined,
|
||||
};
|
||||
});
|
||||
const selectBadges = createMemoizedSelector(selectSdxlSlice, (sdxl) =>
|
||||
sdxl.refinerModel ? ['Enabled'] : undefined
|
||||
);
|
||||
|
||||
export const RefinerSettingsAccordion: React.FC = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isRefinerAvailable = useIsRefinerAvailable();
|
||||
const { badges } = useAppSelector(selector);
|
||||
const badges = useAppSelector(selectBadges);
|
||||
|
||||
if (!isRefinerAvailable) {
|
||||
return (
|
||||
|
@ -1,25 +1,22 @@
|
||||
import { Progress } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { selectSystemSlice } from 'features/system/store/systemSlice';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
|
||||
const progressBarSelector = createMemoizedSelector(
|
||||
|
||||
const selectProgressValue = createSelector(
|
||||
selectSystemSlice,
|
||||
(system) => {
|
||||
return {
|
||||
isConnected: system.isConnected,
|
||||
hasSteps: Boolean(system.denoiseProgress),
|
||||
value: (system.denoiseProgress?.percentage ?? 0) * 100,
|
||||
};
|
||||
}
|
||||
(system) => (system.denoiseProgress?.percentage ?? 0) * 100
|
||||
);
|
||||
|
||||
const ProgressBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { data: queueStatus } = useGetQueueStatusQuery();
|
||||
const { hasSteps, value, isConnected } = useAppSelector(progressBarSelector);
|
||||
const isConnected = useAppSelector((s) => s.system.isConnected);
|
||||
const hasSteps = useAppSelector((s) => Boolean(s.system.denoiseProgress));
|
||||
const value = useAppSelector(selectProgressValue);
|
||||
|
||||
return (
|
||||
<Progress
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvButton } from 'common/components/InvButton/InvButton';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
@ -16,14 +15,10 @@ import { InvSwitch } from 'common/components/InvSwitch/wrapper';
|
||||
import { InvText } from 'common/components/InvText/wrapper';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import { useClearStorage } from 'common/hooks/useClearStorage';
|
||||
import {
|
||||
selectGenerationSlice,
|
||||
shouldUseCpuNoiseChanged,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { shouldUseCpuNoiseChanged } from 'features/parameters/store/generationSlice';
|
||||
import { useClearIntermediates } from 'features/system/components/SettingsModal/useClearIntermediates';
|
||||
import { StickyScrollable } from 'features/system/components/StickyScrollable';
|
||||
import {
|
||||
selectSystemSlice,
|
||||
setEnableImageDebugging,
|
||||
setShouldConfirmOnDelete,
|
||||
setShouldEnableInformationalPopovers,
|
||||
@ -32,10 +27,7 @@ import {
|
||||
shouldUseNSFWCheckerChanged,
|
||||
shouldUseWatermarkerChanged,
|
||||
} from 'features/system/store/systemSlice';
|
||||
import {
|
||||
selectUiSlice,
|
||||
setShouldShowProgressInViewer,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
import { setShouldShowProgressInViewer } from 'features/ui/store/uiSlice';
|
||||
import type { ChangeEvent, ReactElement } from 'react';
|
||||
import { cloneElement, memo, useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -44,37 +36,6 @@ import { useGetAppConfigQuery } from 'services/api/endpoints/appInfo';
|
||||
import { SettingsLanguageSelect } from './SettingsLanguageSelect';
|
||||
import { SettingsLogLevelSelect } from './SettingsLogLevelSelect';
|
||||
|
||||
const selector = createMemoizedSelector(
|
||||
selectSystemSlice,
|
||||
selectUiSlice,
|
||||
selectGenerationSlice,
|
||||
(system, ui, generation) => {
|
||||
const {
|
||||
shouldConfirmOnDelete,
|
||||
enableImageDebugging,
|
||||
shouldLogToConsole,
|
||||
shouldAntialiasProgressImage,
|
||||
shouldUseNSFWChecker,
|
||||
shouldUseWatermarker,
|
||||
shouldEnableInformationalPopovers,
|
||||
} = system;
|
||||
const { shouldUseCpuNoise } = generation;
|
||||
const { shouldShowProgressInViewer } = ui;
|
||||
|
||||
return {
|
||||
shouldUseCpuNoise,
|
||||
shouldConfirmOnDelete,
|
||||
enableImageDebugging,
|
||||
shouldShowProgressInViewer,
|
||||
shouldLogToConsole,
|
||||
shouldAntialiasProgressImage,
|
||||
shouldUseNSFWChecker,
|
||||
shouldUseWatermarker,
|
||||
shouldEnableInformationalPopovers,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
type ConfigOptions = {
|
||||
shouldShowDeveloperSettings: boolean;
|
||||
shouldShowResetWebUiText: boolean;
|
||||
@ -137,17 +98,31 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
|
||||
onClose: onRefreshModalClose,
|
||||
} = useDisclosure();
|
||||
|
||||
const {
|
||||
shouldUseCpuNoise,
|
||||
shouldConfirmOnDelete,
|
||||
enableImageDebugging,
|
||||
shouldShowProgressInViewer,
|
||||
shouldLogToConsole,
|
||||
shouldAntialiasProgressImage,
|
||||
shouldUseNSFWChecker,
|
||||
shouldUseWatermarker,
|
||||
shouldEnableInformationalPopovers,
|
||||
} = useAppSelector(selector);
|
||||
const shouldUseCpuNoise = useAppSelector(
|
||||
(s) => s.generation.shouldUseCpuNoise
|
||||
);
|
||||
const shouldConfirmOnDelete = useAppSelector(
|
||||
(s) => s.system.shouldConfirmOnDelete
|
||||
);
|
||||
const enableImageDebugging = useAppSelector(
|
||||
(s) => s.system.enableImageDebugging
|
||||
);
|
||||
const shouldShowProgressInViewer = useAppSelector(
|
||||
(s) => s.ui.shouldShowProgressInViewer
|
||||
);
|
||||
const shouldLogToConsole = useAppSelector((s) => s.system.shouldLogToConsole);
|
||||
const shouldAntialiasProgressImage = useAppSelector(
|
||||
(s) => s.system.shouldAntialiasProgressImage
|
||||
);
|
||||
const shouldUseNSFWChecker = useAppSelector(
|
||||
(s) => s.system.shouldUseNSFWChecker
|
||||
);
|
||||
const shouldUseWatermarker = useAppSelector(
|
||||
(s) => s.system.shouldUseWatermarker
|
||||
);
|
||||
const shouldEnableInformationalPopovers = useAppSelector(
|
||||
(s) => s.system.shouldEnableInformationalPopovers
|
||||
);
|
||||
|
||||
const clearStorage = useClearStorage();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { selectSystemSlice } from 'features/system/store/systemSlice';
|
||||
|
||||
export const languageSelector = createMemoizedSelector(
|
||||
export const languageSelector = createSelector(
|
||||
selectSystemSlice,
|
||||
(system) => system.language
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user