Merge branch 'main' into lstein/new-model-manager

This commit is contained in:
StAlKeR7779
2023-06-14 17:29:01 +03:00
committed by GitHub
78 changed files with 877 additions and 1049 deletions

View File

@@ -2,7 +2,6 @@ import { Box, ButtonGroup, Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIIconButton from 'common/components/IAIIconButton';
import IAISelect from 'common/components/IAISelect';
import useImageUploader from 'common/hooks/useImageUploader';
import { useSingleAndDoubleClick } from 'common/hooks/useSingleAndDoubleClick';
import {
@@ -25,7 +24,13 @@ import { getCanvasBaseLayer } from 'features/canvas/util/konvaInstanceProvider';
import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es';
import { ChangeEvent } from 'react';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import {
canvasCopiedToClipboard,
canvasDownloadedAsImage,
canvasMerged,
canvasSavedToGallery,
} from 'features/canvas/store/actions';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import {
@@ -43,12 +48,6 @@ import IAICanvasRedoButton from './IAICanvasRedoButton';
import IAICanvasSettingsButtonPopover from './IAICanvasSettingsButtonPopover';
import IAICanvasToolChooserOptions from './IAICanvasToolChooserOptions';
import IAICanvasUndoButton from './IAICanvasUndoButton';
import {
canvasCopiedToClipboard,
canvasDownloadedAsImage,
canvasMerged,
canvasSavedToGallery,
} from 'features/canvas/store/actions';
export const selector = createSelector(
[systemSelector, canvasSelector, isStagingSelector],
@@ -197,8 +196,8 @@ const IAICanvasToolbar = () => {
dispatch(canvasDownloadedAsImage());
};
const handleChangeLayer = (e: ChangeEvent<HTMLSelectElement>) => {
const newLayer = e.target.value as CanvasLayer;
const handleChangeLayer = (v: string) => {
const newLayer = v as CanvasLayer;
dispatch(setLayer(newLayer));
if (newLayer === 'mask' && !isMaskEnabled) {
dispatch(setIsMaskEnabled(true));
@@ -214,13 +213,12 @@ const IAICanvasToolbar = () => {
}}
>
<Box w={24}>
<IAISelect
<IAIMantineSelect
tooltip={`${t('unifiedCanvas.layer')} (Q)`}
tooltipProps={{ hasArrow: true, placement: 'top' }}
value={layer}
validValues={LAYER_NAMES_DICT}
data={LAYER_NAMES_DICT}
onChange={handleChangeLayer}
isDisabled={isStaging}
disabled={isStaging}
/>
</Box>

View File

@@ -866,8 +866,7 @@ export const canvasSlice = createSlice({
});
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
const { image_name, image_origin, image_url, thumbnail_url } =
action.payload;
const { image_name, image_url, thumbnail_url } = action.payload;
state.layerState.objects.forEach((object) => {
if (object.kind === 'image') {

View File

@@ -4,8 +4,8 @@ import { RgbaColor } from 'react-colorful';
import { ImageDTO } from 'services/api';
export const LAYER_NAMES_DICT = [
{ key: 'Base', value: 'base' },
{ key: 'Mask', value: 'mask' },
{ label: 'Base', value: 'base' },
{ label: 'Mask', value: 'mask' },
];
export const LAYER_NAMES = ['base', 'mask'] as const;
@@ -13,9 +13,9 @@ export const LAYER_NAMES = ['base', 'mask'] as const;
export type CanvasLayer = (typeof LAYER_NAMES)[number];
export const BOUNDING_BOX_SCALES_DICT = [
{ key: 'Auto', value: 'auto' },
{ key: 'Manual', value: 'manual' },
{ key: 'None', value: 'none' },
{ label: 'Auto', value: 'auto' },
{ label: 'Manual', value: 'manual' },
{ label: 'None', value: 'none' },
];
export const BOUNDING_BOX_SCALES = ['none', 'auto', 'manual'] as const;

View File

@@ -1,9 +1,8 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAICustomSelect, {
IAICustomSelectOption,
} from 'common/components/IAICustomSelect';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect, {
IAISelectDataType,
} from 'common/components/IAIMantineSelect';
import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke';
import {
CONTROLNET_MODELS,
@@ -12,7 +11,7 @@ import {
import { controlNetModelChanged } from 'features/controlNet/store/controlNetSlice';
import { configSelector } from 'features/system/store/configSelectors';
import { map } from 'lodash-es';
import { ChangeEvent, memo, useCallback } from 'react';
import { memo, useCallback } from 'react';
type ParamControlNetModelProps = {
controlNetId: string;
@@ -20,17 +19,18 @@ type ParamControlNetModelProps = {
};
const selector = createSelector(configSelector, (config) => {
return map(CONTROLNET_MODELS, (m) => ({
key: m.label,
const controlNetModels: IAISelectDataType[] = map(CONTROLNET_MODELS, (m) => ({
label: m.label,
value: m.type,
})).filter((d) => !config.sd.disabledControlNetModels.includes(d.value));
});
})).filter(
(d) =>
!config.sd.disabledControlNetModels.includes(
d.value as ControlNetModelName
)
);
// const DATA: IAICustomSelectOption[] = map(CONTROLNET_MODELS, (m) => ({
// value: m.type,
// label: m.label,
// tooltip: m.type,
// }));
return controlNetModels;
});
const ParamControlNetModel = (props: ParamControlNetModelProps) => {
const { controlNetId, model } = props;
@@ -39,47 +39,23 @@ const ParamControlNetModel = (props: ParamControlNetModelProps) => {
const isReady = useIsReadyToInvoke();
const handleModelChanged = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
(val: string | null) => {
// TODO: do not cast
const model = e.target.value as ControlNetModelName;
const model = val as ControlNetModelName;
dispatch(controlNetModelChanged({ controlNetId, model }));
},
[controlNetId, dispatch]
);
// const handleModelChanged = useCallback(
// (val: string | null | undefined) => {
// // TODO: do not cast
// const model = val as ControlNetModelName;
// dispatch(controlNetModelChanged({ controlNetId, model }));
// },
// [controlNetId, dispatch]
// );
return (
<IAISelect
tooltip={model}
tooltipProps={{ placement: 'top', hasArrow: true }}
validValues={controlNetModels}
<IAIMantineSelect
data={controlNetModels}
value={model}
onChange={handleModelChanged}
isDisabled={!isReady}
// ellipsisPosition="start"
// withCheckIcon
disabled={!isReady}
tooltip={model}
/>
);
// return (
// <IAICustomSelect
// tooltip={model}
// tooltipProps={{ placement: 'top', hasArrow: true }}
// data={DATA}
// value={model}
// onChange={handleModelChanged}
// isDisabled={!isReady}
// ellipsisPosition="start"
// withCheckIcon
// />
// );
};
export default memo(ParamControlNetModel);

View File

@@ -1,64 +1,55 @@
import IAICustomSelect, {
IAICustomSelectOption,
} from 'common/components/IAICustomSelect';
import { ChangeEvent, memo, useCallback } from 'react';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIMantineSelect, {
IAISelectDataType,
} from 'common/components/IAIMantineSelect';
import { map } from 'lodash-es';
import { memo, useCallback } from 'react';
import { CONTROLNET_PROCESSORS } from '../../store/constants';
import { controlNetProcessorTypeChanged } from '../../store/controlNetSlice';
import {
ControlNetProcessorNode,
ControlNetProcessorType,
} from '../../store/types';
import { controlNetProcessorTypeChanged } from '../../store/controlNetSlice';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { CONTROLNET_PROCESSORS } from '../../store/constants';
import { map } from 'lodash-es';
import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke';
import IAISelect from 'common/components/IAISelect';
import { createSelector } from '@reduxjs/toolkit';
import { configSelector } from 'features/system/store/configSelectors';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
type ParamControlNetProcessorSelectProps = {
controlNetId: string;
processorNode: ControlNetProcessorNode;
};
const CONTROLNET_PROCESSOR_TYPES = map(CONTROLNET_PROCESSORS, (p) => ({
value: p.type,
key: p.label,
})).sort((a, b) =>
// sort 'none' to the top
a.value === 'none' ? -1 : b.value === 'none' ? 1 : a.key.localeCompare(b.key)
);
const selector = createSelector(configSelector, (config) => {
return map(CONTROLNET_PROCESSORS, (p) => ({
value: p.type,
key: p.label,
}))
.sort((a, b) =>
// sort 'none' to the top
a.value === 'none'
? -1
: b.value === 'none'
? 1
: a.key.localeCompare(b.key)
const selector = createSelector(
configSelector,
(config) => {
const controlNetProcessors: IAISelectDataType[] = map(
CONTROLNET_PROCESSORS,
(p) => ({
value: p.type,
label: p.label,
})
)
.filter((d) => !config.sd.disabledControlNetProcessors.includes(d.value));
});
.sort((a, b) =>
// sort 'none' to the top
a.value === 'none'
? -1
: b.value === 'none'
? 1
: a.label.localeCompare(b.label)
)
.filter(
(d) =>
!config.sd.disabledControlNetProcessors.includes(
d.value as ControlNetProcessorType
)
);
// const CONTROLNET_PROCESSOR_TYPES: IAICustomSelectOption[] = map(
// CONTROLNET_PROCESSORS,
// (p) => ({
// value: p.type,
// label: p.label,
// tooltip: p.description,
// })
// ).sort((a, b) =>
// // sort 'none' to the top
// a.value === 'none'
// ? -1
// : b.value === 'none'
// ? 1
// : a.label.localeCompare(b.label)
// );
return controlNetProcessors;
},
defaultSelectorOptions
);
const ParamControlNetProcessorSelect = (
props: ParamControlNetProcessorSelectProps
@@ -69,47 +60,26 @@ const ParamControlNetProcessorSelect = (
const controlNetProcessors = useAppSelector(selector);
const handleProcessorTypeChanged = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
(v: string | null) => {
dispatch(
controlNetProcessorTypeChanged({
controlNetId,
processorType: e.target.value as ControlNetProcessorType,
processorType: v as ControlNetProcessorType,
})
);
},
[controlNetId, dispatch]
);
// const handleProcessorTypeChanged = useCallback(
// (v: string | null | undefined) => {
// dispatch(
// controlNetProcessorTypeChanged({
// controlNetId,
// processorType: v as ControlNetProcessorType,
// })
// );
// },
// [controlNetId, dispatch]
// );
return (
<IAISelect
<IAIMantineSelect
label="Processor"
value={processorNode.type ?? 'canny_image_processor'}
validValues={controlNetProcessors}
data={controlNetProcessors}
onChange={handleProcessorTypeChanged}
isDisabled={!isReady}
disabled={!isReady}
/>
);
// return (
// <IAICustomSelect
// label="Processor"
// value={processorNode.type ?? 'canny_image_processor'}
// data={CONTROLNET_PROCESSOR_TYPES}
// onChange={handleProcessorTypeChanged}
// withCheckIcon
// isDisabled={!isReady}
// />
// );
};
export default memo(ParamControlNetProcessorSelect);

View File

@@ -271,8 +271,7 @@ export const controlNetSlice = createSlice({
});
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
const { image_name, image_origin, image_url, thumbnail_url } =
action.payload;
const { image_name, image_url, thumbnail_url } = action.payload;
forEach(state.controlNets, (c) => {
if (c.controlImage?.image_name === image_name) {

View File

@@ -9,15 +9,15 @@ import {
Tooltip,
} from '@chakra-ui/react';
import { useAppDispatch } from 'app/store/storeHooks';
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
import { setShouldShowImageDetails } from 'features/ui/store/uiSlice';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
import { FaCopy } from 'react-icons/fa';
import { IoArrowUndoCircleOutline } from 'react-icons/io5';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { ImageDTO } from 'services/api';
import { useRecallParameters } from 'features/parameters/hooks/useRecallParameters';
type MetadataItemProps = {
isLink?: boolean;
@@ -324,7 +324,7 @@ const ImageMetadataViewer = memo(({ image }: ImageMetadataViewerProps) => {
borderRadius: 'base',
bg: 'whiteAlpha.500',
_dark: { bg: 'blackAlpha.500' },
w: 'max-content',
w: 'full',
}}
>
<pre>{metadataJSON}</pre>

View File

@@ -59,8 +59,7 @@ export const gallerySlice = createSlice({
}
});
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
const { image_name, image_origin, image_url, thumbnail_url } =
action.payload;
const { image_name, image_url, thumbnail_url } = action.payload;
if (state.selectedImage?.image_name === image_name) {
state.selectedImage.image_url = image_url;

View File

@@ -86,8 +86,7 @@ const imagesSlice = createSlice({
imagesAdapter.removeOne(state, imageName);
});
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
const { image_name, image_origin, image_url, thumbnail_url } =
action.payload;
const { image_name, image_url, thumbnail_url } = action.payload;
imagesAdapter.updateOne(state, {
id: image_name,

View File

@@ -103,8 +103,7 @@ const nodesSlice = createSlice({
});
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
const { image_name, image_origin, image_url, thumbnail_url } =
action.payload;
const { image_name, image_url, thumbnail_url } = action.payload;
state.nodes.forEach((node) => {
forEach(node.data.inputs, (input) => {

View File

@@ -66,17 +66,15 @@ export const addControlNetToLinearGraph = (
if (processedControlImage && processorType !== 'none') {
// We've already processed the image in the app, so we can just use the processed image
const { image_name, image_origin } = processedControlImage;
const { image_name } = processedControlImage;
controlNetNode.image = {
image_name,
image_origin,
};
} else if (controlImage) {
// The control image is preprocessed
const { image_name, image_origin } = controlImage;
const { image_name } = controlImage;
controlNetNode.image = {
image_name,
image_origin,
};
} else {
// Skip ControlNets without an unprocessed image - should never happen if everything is working correctly

View File

@@ -354,7 +354,6 @@ export const buildImageToImageGraph = (state: RootState): Graph => {
type: 'img_resize',
image: {
image_name: initialImage.image_name,
image_origin: initialImage.image_origin,
},
is_intermediate: true,
height,
@@ -392,7 +391,6 @@ export const buildImageToImageGraph = (state: RootState): Graph => {
// We are not resizing, so we need to set the image on the `IMAGE_TO_LATENTS` node explicitly
set(graph.nodes[IMAGE_TO_LATENTS], 'image', {
image_name: initialImage.image_name,
image_origin: initialImage.image_origin,
});
// Pass the image's dimensions to the `NOISE` node

View File

@@ -57,8 +57,7 @@ export const buildImg2ImgNode = (
}
imageToImageNode.image = {
image_name: initialImage.name,
image_origin: initialImage.type,
image_name: initialImage.image_name,
};
}

View File

@@ -1,12 +1,12 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { setInfillMethod } from 'features/parameters/store/generationSlice';
import { systemSelector } from 'features/system/store/systemSelectors';
import { ChangeEvent, memo, useCallback } from 'react';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
@@ -30,17 +30,17 @@ const ParamInfillMethod = () => {
const { t } = useTranslation();
const handleChange = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
dispatch(setInfillMethod(e.target.value));
(v: string) => {
dispatch(setInfillMethod(v));
},
[dispatch]
);
return (
<IAISelect
<IAIMantineSelect
label={t('parameters.infillMethod')}
value={infillMethod}
validValues={infillMethods}
data={infillMethods}
onChange={handleChange}
/>
);

View File

@@ -1,15 +1,15 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setBoundingBoxScaleMethod } from 'features/canvas/store/canvasSlice';
import {
BoundingBoxScale,
BOUNDING_BOX_SCALES_DICT,
BoundingBoxScale,
} from 'features/canvas/store/canvasTypes';
import { ChangeEvent, memo } from 'react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
@@ -30,16 +30,14 @@ const ParamScaleBeforeProcessing = () => {
const { t } = useTranslation();
const handleChangeBoundingBoxScaleMethod = (
e: ChangeEvent<HTMLSelectElement>
) => {
dispatch(setBoundingBoxScaleMethod(e.target.value as BoundingBoxScale));
const handleChangeBoundingBoxScaleMethod = (v: string) => {
dispatch(setBoundingBoxScaleMethod(v as BoundingBoxScale));
};
return (
<IAISelect
<IAIMantineSelect
label={t('parameters.scaleBeforeProcessing')}
validValues={BOUNDING_BOX_SCALES_DICT}
data={BOUNDING_BOX_SCALES_DICT}
value={boundingBoxScale}
onChange={handleChangeBoundingBoxScaleMethod}
/>

View File

@@ -2,23 +2,20 @@ import { createSelector } from '@reduxjs/toolkit';
import { Scheduler } from 'app/constants';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAICustomSelect from 'common/components/IAICustomSelect';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect, {
IAISelectDataType,
} from 'common/components/IAIMantineSelect';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { setScheduler } from 'features/parameters/store/generationSlice';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { ChangeEvent, memo, useCallback } from 'react';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
[uiSelector, generationSelector],
(ui, generation) => {
// TODO: DPMSolverSinglestepScheduler is fixed in https://github.com/huggingface/diffusers/pull/3413
// but we need to wait for the next release before removing this special handling.
const allSchedulers = ui.schedulers
.filter((scheduler) => {
return !['dpmpp_2s'].includes(scheduler);
})
const allSchedulers: string[] = ui.schedulers
.slice()
.sort((a, b) => a.localeCompare(b));
return {
@@ -36,39 +33,23 @@ const ParamScheduler = () => {
const { t } = useTranslation();
const handleChange = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
dispatch(setScheduler(e.target.value as Scheduler));
(v: string | null) => {
if (!v) {
return;
}
dispatch(setScheduler(v as Scheduler));
},
[dispatch]
);
// const handleChange = useCallback(
// (v: string | null | undefined) => {
// if (!v) {
// return;
// }
// dispatch(setScheduler(v as Scheduler));
// },
// [dispatch]
// );
return (
<IAISelect
<IAIMantineSelect
label={t('parameters.scheduler')}
value={scheduler}
validValues={allSchedulers}
data={allSchedulers}
onChange={handleChange}
/>
);
// return (
// <IAICustomSelect
// label={t('parameters.scheduler')}
// value={scheduler}
// data={allSchedulers}
// onChange={handleChange}
// withCheckIcon
// />
// );
};
export default memo(ParamScheduler);

View File

@@ -1,12 +1,11 @@
import { FACETOOL_TYPES } from 'app/constants';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import {
FacetoolType,
setFacetoolType,
} from 'features/parameters/store/postprocessingSlice';
import { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
export default function FaceRestoreType() {
@@ -17,13 +16,13 @@ export default function FaceRestoreType() {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const handleChangeFacetoolType = (e: ChangeEvent<HTMLSelectElement>) =>
dispatch(setFacetoolType(e.target.value as FacetoolType));
const handleChangeFacetoolType = (v: string) =>
dispatch(setFacetoolType(v as FacetoolType));
return (
<IAISelect
<IAIMantineSelect
label={t('parameters.type')}
validValues={FACETOOL_TYPES.concat()}
data={FACETOOL_TYPES.concat()}
value={facetoolType}
onChange={handleChangeFacetoolType}
/>

View File

@@ -1,12 +1,11 @@
import { UPSCALING_LEVELS } from 'app/constants';
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import {
setUpscalingLevel,
UpscalingLevel,
setUpscalingLevel,
} from 'features/parameters/store/postprocessingSlice';
import type { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
export default function UpscaleScale() {
@@ -21,16 +20,16 @@ export default function UpscaleScale() {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const handleChangeLevel = (e: ChangeEvent<HTMLSelectElement>) =>
dispatch(setUpscalingLevel(Number(e.target.value) as UpscalingLevel));
const handleChangeLevel = (v: string) =>
dispatch(setUpscalingLevel(Number(v) as UpscalingLevel));
return (
<IAISelect
isDisabled={!isESRGANAvailable}
<IAIMantineSelect
disabled={!isESRGANAvailable}
label={t('parameters.scale')}
value={upscalingLevel}
value={String(upscalingLevel)}
onChange={handleChangeLevel}
validValues={UPSCALING_LEVELS}
data={UPSCALING_LEVELS}
/>
);
}

View File

@@ -1,11 +1,5 @@
import { createAction } from '@reduxjs/toolkit';
import { isObject } from 'lodash-es';
import { ImageDTO, ResourceOrigin } from 'services/api';
export type ImageNameAndOrigin = {
image_name: string;
image_origin: ResourceOrigin;
};
import { ImageDTO } from 'services/api';
export const initialImageSelected = createAction<ImageDTO | string | undefined>(
'generation/initialImageSelected'

View File

@@ -234,8 +234,7 @@ export const generationSlice = createSlice({
});
builder.addCase(imageUrlsReceived.fulfilled, (state, action) => {
const { image_name, image_origin, image_url, thumbnail_url } =
action.payload;
const { image_name, image_url, thumbnail_url } = action.payload;
if (state.initialImage?.image_name === image_name) {
state.initialImage.image_url = image_url;

View File

@@ -1,17 +1,16 @@
import { createSelector } from '@reduxjs/toolkit';
import { ChangeEvent, memo, useCallback } from 'react';
import { isEqual } from 'lodash-es';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { selectModelsAll, selectModelsById } from '../store/modelSlice';
import { RootState } from 'app/store/store';
import { modelSelected } from 'features/parameters/store/generationSlice';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIMantineSelect, {
IAISelectDataType,
} from 'common/components/IAIMantineSelect';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import IAICustomSelect, {
IAICustomSelectOption,
} from 'common/components/IAICustomSelect';
import IAISelect from 'common/components/IAISelect';
import { modelSelected } from 'features/parameters/store/generationSlice';
import { selectModelsAll, selectModelsById } from '../store/modelSlice';
const selector = createSelector(
[(state: RootState) => state, generationSelector],
@@ -19,18 +18,11 @@ const selector = createSelector(
const selectedModel = selectModelsById(state, generation.model);
const modelData = selectModelsAll(state)
.map((m) => ({
.map<IAISelectDataType>((m) => ({
value: m.name,
key: m.name,
label: m.name,
}))
.sort((a, b) => a.key.localeCompare(b.key));
// const modelData = selectModelsAll(state)
// .map<IAICustomSelectOption>((m) => ({
// value: m.name,
// label: m.name,
// tooltip: m.description,
// }))
// .sort((a, b) => a.label.localeCompare(b.label));
.sort((a, b) => a.label.localeCompare(b.label));
return {
selectedModel,
modelData,
@@ -48,43 +40,25 @@ const ModelSelect = () => {
const { t } = useTranslation();
const { selectedModel, modelData } = useAppSelector(selector);
const handleChangeModel = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
dispatch(modelSelected(e.target.value));
(v: string | null) => {
if (!v) {
return;
}
dispatch(modelSelected(v));
},
[dispatch]
);
// const handleChangeModel = useCallback(
// (v: string | null | undefined) => {
// if (!v) {
// return;
// }
// dispatch(modelSelected(v));
// },
// [dispatch]
// );
return (
<IAISelect
label={t('modelManager.model')}
<IAIMantineSelect
tooltip={selectedModel?.description}
validValues={modelData}
label={t('modelManager.model')}
value={selectedModel?.name ?? ''}
placeholder="Pick one"
data={modelData}
onChange={handleChangeModel}
tooltipProps={{ placement: 'top', hasArrow: true }}
/>
);
// return (
// <IAICustomSelect
// label={t('modelManager.model')}
// tooltip={selectedModel?.description}
// data={modelData}
// value={selectedModel?.name ?? ''}
// onChange={handleChangeModel}
// withCheckIcon={true}
// tooltipProps={{ placement: 'top', hasArrow: true }}
// />
// );
};
export default memo(ModelSelect);

View File

@@ -13,19 +13,21 @@ import {
useDisclosure,
} from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { VALID_LOG_LEVELS } from 'app/logging/useLogger';
import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import IAISwitch from 'common/components/IAISwitch';
import { systemSelector } from 'features/system/store/systemSelectors';
import {
SystemState,
consoleLogLevelChanged,
setEnableImageDebugging,
setShouldConfirmOnDelete,
setShouldDisplayGuides,
shouldAntialiasProgressImageChanged,
shouldLogToConsoleChanged,
SystemState,
} from 'features/system/store/systemSlice';
import { uiSelector } from 'features/ui/store/uiSelectors';
import {
@@ -37,15 +39,13 @@ import { UIState } from 'features/ui/store/uiTypes';
import { isEqual } from 'lodash-es';
import {
ChangeEvent,
cloneElement,
ReactElement,
cloneElement,
useCallback,
useEffect,
} from 'react';
import { useTranslation } from 'react-i18next';
import { VALID_LOG_LEVELS } from 'app/logging/useLogger';
import { LogLevelName } from 'roarr';
import { LOCALSTORAGE_KEYS, LOCALSTORAGE_PREFIX } from 'app/store/constants';
import SettingsSchedulers from './SettingsSchedulers';
const selector = createSelector(
@@ -157,8 +157,8 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
}, [onSettingsModalClose, onRefreshModalOpen]);
const handleLogLevelChanged = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
dispatch(consoleLogLevelChanged(e.target.value as LogLevelName));
(v: string) => {
dispatch(consoleLogLevelChanged(v as LogLevelName));
},
[dispatch]
);
@@ -255,14 +255,12 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => {
isChecked={shouldLogToConsole}
onChange={handleLogToConsoleChanged}
/>
<IAISelect
horizontal
spaceEvenly
isDisabled={!shouldLogToConsole}
<IAIMantineSelect
disabled={!shouldLogToConsole}
label={t('settings.consoleLogLevel')}
onChange={handleLogLevelChanged}
value={consoleLogLevel}
validValues={VALID_LOG_LEVELS.concat()}
data={VALID_LOG_LEVELS.concat()}
/>
<IAISwitch
label={t('settings.enableImageDebugging')}

View File

@@ -1,5 +1,4 @@
import {
Box,
Menu,
MenuButton,
MenuItemOption,
@@ -13,7 +12,6 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';
import { setSchedulers } from 'features/ui/store/uiSlice';
import { isArray } from 'lodash-es';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { useTranslation } from 'react-i18next';
export default function SettingsSchedulers() {

View File

@@ -1,21 +1,21 @@
import { Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { memo, useMemo } from 'react';
import { Box, Flex } from '@chakra-ui/react';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import InvokeAILogoComponent from 'features/system/components/InvokeAILogoComponent';
import OverlayScrollable from './common/OverlayScrollable';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import {
activeTabNameSelector,
uiSelector,
} from 'features/ui/store/uiSelectors';
import { setShouldShowParametersPanel } from 'features/ui/store/uiSlice';
import ResizableDrawer from './common/ResizableDrawer/ResizableDrawer';
import { memo, useMemo } from 'react';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import PinParametersPanelButton from './PinParametersPanelButton';
import TextToImageTabParameters from './tabs/TextToImage/TextToImageTabParameters';
import OverlayScrollable from './common/OverlayScrollable';
import ResizableDrawer from './common/ResizableDrawer/ResizableDrawer';
import ImageToImageTabParameters from './tabs/ImageToImage/ImageToImageTabParameters';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import TextToImageTabParameters from './tabs/TextToImage/TextToImageTabParameters';
import UnifiedCanvasParameters from './tabs/UnifiedCanvas/UnifiedCanvasParameters';
const selector = createSelector(

View File

@@ -1,11 +1,11 @@
import { Box, Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { PropsWithChildren, memo } from 'react';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import OverlayScrollable from './common/OverlayScrollable';
import PinParametersPanelButton from './PinParametersPanelButton';
import { createSelector } from '@reduxjs/toolkit';
import { uiSelector } from '../store/uiSelectors';
import { useAppSelector } from 'app/store/storeHooks';
import PinParametersPanelButton from './PinParametersPanelButton';
import OverlayScrollable from './common/OverlayScrollable';
const selector = createSelector(uiSelector, (ui) => {
const { shouldPinParametersPanel, shouldShowParametersPanel } = ui;
@@ -35,19 +35,27 @@ const ParametersPinnedWrapper = (props: ParametersPinnedWrapperProps) => {
flexShrink: 0,
}}
>
<OverlayScrollable>
<Flex
sx={{
gap: 2,
flexDirection: 'column',
h: 'full',
w: 'full',
position: 'absolute',
}}
>
{props.children}
</Flex>
</OverlayScrollable>
<Flex
sx={{
gap: 2,
flexDirection: 'column',
h: 'full',
w: 'full',
position: 'absolute',
}}
>
<OverlayScrollable>
<Flex
sx={{
flexDirection: 'column',
gap: 2,
}}
>
{props.children}
</Flex>
</OverlayScrollable>
</Flex>
<PinParametersPanelButton
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
/>

View File

@@ -1,6 +1,5 @@
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { PropsWithChildren, memo } from 'react';
const OverlayScrollable = (props: PropsWithChildren) => {
return (
<OverlayScrollbarsComponent
@@ -20,5 +19,4 @@ const OverlayScrollable = (props: PropsWithChildren) => {
</OverlayScrollbarsComponent>
);
};
export default memo(OverlayScrollable);

View File

@@ -1,14 +1,17 @@
import { Box, Flex } from '@chakra-ui/react';
import { memo, useCallback, useRef } from 'react';
import { Panel, PanelGroup } from 'react-resizable-panels';
import { useAppDispatch } from 'app/store/storeHooks';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import ResizeHandle from '../ResizeHandle';
import ImageToImageTabParameters from './ImageToImageTabParameters';
import TextToImageTabMain from '../TextToImage/TextToImageTabMain';
import { ImperativePanelGroupHandle } from 'react-resizable-panels';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
import InitialImageDisplay from 'features/parameters/components/Parameters/ImageToImage/InitialImageDisplay';
import { memo, useCallback, useRef } from 'react';
import {
ImperativePanelGroupHandle,
Panel,
PanelGroup,
} from 'react-resizable-panels';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
import ResizeHandle from '../ResizeHandle';
import TextToImageTabMain from '../TextToImage/TextToImageTabMain';
import ImageToImageTabParameters from './ImageToImageTabParameters';
const ImageToImageTab = () => {
const dispatch = useAppDispatch();

View File

@@ -1,8 +1,8 @@
import { Flex } from '@chakra-ui/react';
import { memo } from 'react';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
import TextToImageTabMain from './TextToImageTabMain';
import TextToImageTabParameters from './TextToImageTabParameters';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
const TextToImageTab = () => {
return (

View File

@@ -1,6 +1,6 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISelect from 'common/components/IAISelect';
import IAIMantineSelect from 'common/components/IAIMantineSelect';
import {
canvasSelector,
isStagingSelector,
@@ -12,7 +12,6 @@ import {
} from 'features/canvas/store/canvasTypes';
import { isEqual } from 'lodash-es';
import { ChangeEvent } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { useTranslation } from 'react-i18next';
@@ -51,22 +50,22 @@ export default function UnifiedCanvasLayerSelect() {
[layer]
);
const handleChangeLayer = (e: ChangeEvent<HTMLSelectElement>) => {
const newLayer = e.target.value as CanvasLayer;
const handleChangeLayer = (v: string) => {
const newLayer = v as CanvasLayer;
dispatch(setLayer(newLayer));
if (newLayer === 'mask' && !isMaskEnabled) {
dispatch(setIsMaskEnabled(true));
}
};
return (
<IAISelect
<IAIMantineSelect
tooltip={`${t('unifiedCanvas.layer')} (Q)`}
aria-label={`${t('unifiedCanvas.layer')} (Q)`}
tooltipProps={{ hasArrow: true, placement: 'top' }}
value={layer}
validValues={LAYER_NAMES_DICT}
data={LAYER_NAMES_DICT}
onChange={handleChangeLayer}
isDisabled={isStaging}
disabled={isStaging}
w="full"
/>
);
}

View File

@@ -2,6 +2,7 @@ import { Flex } from '@chakra-ui/react';
import IAICanvasRedoButton from 'features/canvas/components/IAICanvasToolbar/IAICanvasRedoButton';
import IAICanvasUndoButton from 'features/canvas/components/IAICanvasToolbar/IAICanvasUndoButton';
import UnifiedCanvasSettings from './UnifiedCanvasToolSettings/UnifiedCanvasSettings';
import UnifiedCanvasCopyToClipboard from './UnifiedCanvasToolbar/UnifiedCanvasCopyToClipboard';
import UnifiedCanvasDownloadImage from './UnifiedCanvasToolbar/UnifiedCanvasDownloadImage';
import UnifiedCanvasFileUploader from './UnifiedCanvasToolbar/UnifiedCanvasFileUploader';
@@ -13,11 +14,10 @@ import UnifiedCanvasResetCanvas from './UnifiedCanvasToolbar/UnifiedCanvasResetC
import UnifiedCanvasResetView from './UnifiedCanvasToolbar/UnifiedCanvasResetView';
import UnifiedCanvasSaveToGallery from './UnifiedCanvasToolbar/UnifiedCanvasSaveToGallery';
import UnifiedCanvasToolSelect from './UnifiedCanvasToolbar/UnifiedCanvasToolSelect';
import UnifiedCanvasSettings from './UnifiedCanvasToolSettings/UnifiedCanvasSettings';
const UnifiedCanvasToolbarBeta = () => {
return (
<Flex flexDirection="column" rowGap={2}>
<Flex flexDirection="column" rowGap={2} width="min-content">
<UnifiedCanvasLayerSelect />
<UnifiedCanvasToolSelect />

View File

@@ -1,8 +1,8 @@
import { Flex } from '@chakra-ui/react';
import { memo } from 'react';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
import UnifiedCanvasContent from './UnifiedCanvasContent';
import UnifiedCanvasParameters from './UnifiedCanvasParameters';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
const UnifiedCanvasTab = () => {
return (