feat(ui): organize parameters panels

This commit is contained in:
psychedelicious 2023-05-09 18:12:34 +10:00
parent ec6c8e2a38
commit c565812723
64 changed files with 880 additions and 996 deletions

View File

@ -19,8 +19,6 @@ import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
import { GalleryState } from 'features/gallery/store/gallerySlice';
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
import FaceRestoreSettings from 'features/parameters/components/AdvancedParameters/FaceRestore/FaceRestoreSettings';
import UpscaleSettings from 'features/parameters/components/AdvancedParameters/Upscale/UpscaleSettings';
import {
initialImageChanged,
setAllParameters,
@ -69,6 +67,8 @@ import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
import { useParameters } from 'features/parameters/hooks/useParameters';
import { initialImageSelected } from 'features/parameters/store/actions';
import { requestedImageDeletion } from '../store/actions';
import FaceRestoreSettings from 'features/parameters/components/Parameters/FaceRestore/FaceRestoreSettings';
import UpscaleSettings from 'features/parameters/components/Parameters/Upscale/UpscaleSettings';
const currentImageButtonsSelector = createSelector(
[

View File

@ -1,37 +0,0 @@
import {
AccordionButton,
AccordionIcon,
AccordionItem,
AccordionPanel,
Box,
Flex,
} from '@chakra-ui/react';
import GuideIcon from 'common/components/GuideIcon';
import { ParametersAccordionItem } from '../ParametersAccordion';
type InvokeAccordionItemProps = {
accordionItem: ParametersAccordionItem;
};
export default function InvokeAccordionItem({
accordionItem,
}: InvokeAccordionItemProps) {
const { header, feature, content, additionalHeaderComponents } =
accordionItem;
return (
<AccordionItem>
<AccordionButton>
<Flex width="100%" gap={2} align="center">
<Box flexGrow={1} textAlign="start">
{header}
</Box>
{additionalHeaderComponents}
{/* {feature && <GuideIcon feature={feature} />} */}
<AccordionIcon />
</Flex>
</AccordionButton>
<AccordionPanel p={4}>{content}</AccordionPanel>
</AccordionItem>
);
}

View File

@ -1,113 +0,0 @@
import { Box, VStack } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
import { isEqual } from 'lodash-es';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
canvasSelector,
(canvas) => {
const { boundingBoxDimensions, boundingBoxScaleMethod: boundingBoxScale } =
canvas;
return {
boundingBoxDimensions,
boundingBoxScale,
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
const BoundingBoxSettings = () => {
const dispatch = useAppDispatch();
const { boundingBoxDimensions } = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeWidth = (v: number) => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
width: Math.floor(v),
})
);
};
const handleChangeHeight = (v: number) => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
height: Math.floor(v),
})
);
};
const handleResetWidth = () => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
width: Math.floor(512),
})
);
};
const handleResetHeight = () => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
height: Math.floor(512),
})
);
};
return (
<VStack gap={2} alignItems="stretch">
<IAISlider
label={t('parameters.width')}
min={64}
max={1024}
step={64}
value={boundingBoxDimensions.width}
onChange={handleChangeWidth}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetWidth}
/>
<IAISlider
label={t('parameters.height')}
min={64}
max={1024}
step={64}
value={boundingBoxDimensions.height}
onChange={handleChangeHeight}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetHeight}
/>
</VStack>
);
};
export default BoundingBoxSettings;
export const BoundingBoxSettingsHeader = () => {
const { t } = useTranslation();
return (
<Box flex="1" textAlign="start">
{t('parameters.boundingBoxHeader')}
</Box>
);
};

View File

@ -1,174 +0,0 @@
import { VStack } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISelect from 'common/components/IAISelect';
import IAISlider from 'common/components/IAISlider';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import {
setBoundingBoxScaleMethod,
setScaledBoundingBoxDimensions,
} from 'features/canvas/store/canvasSlice';
import {
BoundingBoxScale,
BOUNDING_BOX_SCALES_DICT,
} from 'features/canvas/store/canvasTypes';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import {
setInfillMethod,
setTileSize,
} from 'features/parameters/store/generationSlice';
import { systemSelector } from 'features/system/store/systemSelectors';
import { isEqual } from 'lodash-es';
import { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
[generationSelector, systemSelector, canvasSelector],
(parameters, system, canvas) => {
const { tileSize, infillMethod } = parameters;
const { infillMethods } = system;
const {
boundingBoxScaleMethod: boundingBoxScale,
scaledBoundingBoxDimensions,
} = canvas;
return {
boundingBoxScale,
scaledBoundingBoxDimensions,
tileSize,
infillMethod,
infillMethods,
isManual: boundingBoxScale === 'manual',
};
},
{
memoizeOptions: {
resultEqualityCheck: isEqual,
},
}
);
const InfillAndScalingSettings = () => {
const dispatch = useAppDispatch();
const {
tileSize,
infillMethod,
infillMethods,
boundingBoxScale,
isManual,
scaledBoundingBoxDimensions,
} = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeScaledWidth = (v: number) => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
width: Math.floor(v),
})
);
};
const handleChangeScaledHeight = (v: number) => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
height: Math.floor(v),
})
);
};
const handleResetScaledWidth = () => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
width: Math.floor(512),
})
);
};
const handleResetScaledHeight = () => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
height: Math.floor(512),
})
);
};
const handleChangeBoundingBoxScaleMethod = (
e: ChangeEvent<HTMLSelectElement>
) => {
dispatch(setBoundingBoxScaleMethod(e.target.value as BoundingBoxScale));
};
return (
<VStack gap={2} alignItems="stretch">
<IAISelect
label={t('parameters.scaleBeforeProcessing')}
validValues={BOUNDING_BOX_SCALES_DICT}
value={boundingBoxScale}
onChange={handleChangeBoundingBoxScaleMethod}
/>
<IAISlider
isDisabled={!isManual}
label={t('parameters.scaledWidth')}
min={64}
max={1024}
step={64}
value={scaledBoundingBoxDimensions.width}
onChange={handleChangeScaledWidth}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetScaledWidth}
/>
<IAISlider
isDisabled={!isManual}
label={t('parameters.scaledHeight')}
min={64}
max={1024}
step={64}
value={scaledBoundingBoxDimensions.height}
onChange={handleChangeScaledHeight}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetScaledHeight}
/>
<IAISelect
label={t('parameters.infillMethod')}
value={infillMethod}
validValues={infillMethods}
onChange={(e) => dispatch(setInfillMethod(e.target.value))}
/>
<IAISlider
isDisabled={infillMethod !== 'tile'}
label={t('parameters.tileSize')}
min={16}
max={64}
sliderNumberInputProps={{ max: 256 }}
value={tileSize}
onChange={(v) => {
dispatch(setTileSize(v));
}}
withInput
withSliderMarks
withReset
handleReset={() => {
dispatch(setTileSize(32));
}}
/>
</VStack>
);
};
export default InfillAndScalingSettings;

View File

@ -1,18 +0,0 @@
import { VStack } from '@chakra-ui/react';
import ParamSeamBlur from './ParamSeamBlur';
import ParamSeamSize from './ParamSeamSize';
import ParamSeamSteps from './ParamSeamSteps';
import ParamSeamStrength from './ParamSeamStrength';
const SeamCorrectionSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<ParamSeamSize />
<ParamSeamBlur />
<ParamSeamStrength />
<ParamSeamSteps />
</VStack>
);
};
export default SeamCorrectionSettings;

View File

@ -1,32 +0,0 @@
import { memo, useState } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import ImageToImageSettings from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageSettings';
import { useAppSelector } from 'app/store/storeHooks';
import { RootState } from 'app/store/store';
import { Box } from '@chakra-ui/react';
const AnimatedImageToImagePanel = () => {
const isImageToImageEnabled = useAppSelector(
(state: RootState) => state.generation.isImageToImageEnabled
);
return (
<AnimatePresence>
{isImageToImageEnabled && (
<motion.div
initial={{ opacity: 0, scale: 0, width: 0 }}
animate={{ opacity: 1, scale: 1, width: '28rem' }}
exit={{ opacity: 0, scale: 0, width: 0 }}
transition={{ type: 'spring', bounce: 0, duration: 0.35 }}
>
<Box sx={{ h: 'full', w: 'full' }}>
<ImageToImageSettings />
</Box>
</motion.div>
)}
</AnimatePresence>
);
};
export default memo(AnimatedImageToImagePanel);

View File

@ -1,45 +0,0 @@
import { HEIGHTS } from 'app/constants';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISelect from 'common/components/IAISelect';
import IAISlider from 'common/components/IAISlider';
import { setHeight } from 'features/parameters/store/generationSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useTranslation } from 'react-i18next';
export default function MainHeight() {
const height = useAppSelector((state: RootState) => state.generation.height);
const shouldUseSliders = useAppSelector(
(state: RootState) => state.ui.shouldUseSliders
);
const activeTabName = useAppSelector(activeTabNameSelector);
const dispatch = useAppDispatch();
const { t } = useTranslation();
return shouldUseSliders ? (
<IAISlider
isDisabled={activeTabName === 'unifiedCanvas'}
label={t('parameters.height')}
value={height}
min={64}
step={8}
max={2048}
onChange={(v) => dispatch(setHeight(v))}
handleReset={() => dispatch(setHeight(512))}
withInput
withReset
withSliderMarks
sliderNumberInputProps={{ max: 15360 }}
/>
) : (
<IAISelect
isDisabled={activeTabName === 'unifiedCanvas'}
label={t('parameters.height')}
value={height}
flexGrow={1}
onChange={(e) => dispatch(setHeight(Number(e.target.value)))}
validValues={HEIGHTS}
/>
);
}

View File

@ -1,56 +0,0 @@
import { memo } from 'react';
import { Box, Flex, VStack } from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import ModelSelect from 'features/system/components/ModelSelect';
import ParamHeight from 'features/parameters/components/Parameters/ParamHeight';
import ParamCFGScale from 'features/parameters/components/Parameters/ParamCFGScale';
import ParamIterations from 'features/parameters/components/Parameters/ParamIterations';
import ParamScheduler from 'features/parameters/components/Parameters/ParamScheduler';
import ParamSteps from 'features/parameters/components/Parameters/ParamSteps';
import ParamWidth from 'features/parameters/components/Parameters/ParamWidth';
const MainSettings = () => {
const shouldUseSliders = useAppSelector(
(state: RootState) => state.ui.shouldUseSliders
);
return shouldUseSliders ? (
<VStack gap={2}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</VStack>
) : (
<Flex gap={3} flexDirection="column">
<Flex gap={3}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</Flex>
);
};
export default memo(MainSettings);

View File

@ -1,46 +0,0 @@
import { WIDTHS } from 'app/constants';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISelect from 'common/components/IAISelect';
import IAISlider from 'common/components/IAISlider';
import { setWidth } from 'features/parameters/store/generationSlice';
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
import { useTranslation } from 'react-i18next';
export default function MainWidth() {
const width = useAppSelector((state: RootState) => state.generation.width);
const shouldUseSliders = useAppSelector(
(state: RootState) => state.ui.shouldUseSliders
);
const activeTabName = useAppSelector(activeTabNameSelector);
const { t } = useTranslation();
const dispatch = useAppDispatch();
return shouldUseSliders ? (
<IAISlider
isDisabled={activeTabName === 'unifiedCanvas'}
label={t('parameters.width')}
value={width}
min={8}
step={64}
max={2048}
onChange={(v) => dispatch(setWidth(v))}
handleReset={() => dispatch(setWidth(512))}
withInput
withReset
withSliderMarks
inputReadOnly
sliderNumberInputProps={{ max: 15360 }}
/>
) : (
<IAISelect
isDisabled={activeTabName === 'unifiedCanvas'}
label={t('parameters.width')}
value={width}
flexGrow={1}
onChange={(e) => dispatch(setWidth(Number(e.target.value)))}
validValues={WIDTHS}
/>
);
}

View File

@ -0,0 +1,26 @@
import { Flex, useDisclosure } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import IAICollapse from 'common/components/IAICollapse';
import { memo } from 'react';
import ParamBoundingBoxWidth from './ParamBoundingBoxWidth';
import ParamBoundingBoxHeight from './ParamBoundingBoxHeight';
const ParamBoundingBoxCollapse = () => {
const { t } = useTranslation();
const { isOpen, onToggle } = useDisclosure();
return (
<IAICollapse
label={t('parameters.boundingBoxHeader')}
isOpen={isOpen}
onToggle={onToggle}
>
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamBoundingBoxWidth />
<ParamBoundingBoxHeight />
</Flex>
</IAICollapse>
);
};
export default memo(ParamBoundingBoxCollapse);

View File

@ -0,0 +1,64 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
canvasSelector,
(canvas) => {
const { boundingBoxDimensions } = canvas;
return {
boundingBoxDimensions,
};
},
defaultSelectorOptions
);
const ParamBoundingBoxWidth = () => {
const dispatch = useAppDispatch();
const { boundingBoxDimensions } = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeHeight = (v: number) => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
height: Math.floor(v),
})
);
};
const handleResetHeight = () => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
height: Math.floor(512),
})
);
};
return (
<IAISlider
label={t('parameters.height')}
min={64}
max={1024}
step={64}
value={boundingBoxDimensions.height}
onChange={handleChangeHeight}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetHeight}
/>
);
};
export default memo(ParamBoundingBoxWidth);

View File

@ -0,0 +1,64 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
canvasSelector,
(canvas) => {
const { boundingBoxDimensions } = canvas;
return {
boundingBoxDimensions,
};
},
defaultSelectorOptions
);
const ParamBoundingBoxWidth = () => {
const dispatch = useAppDispatch();
const { boundingBoxDimensions } = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeWidth = (v: number) => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
width: Math.floor(v),
})
);
};
const handleResetWidth = () => {
dispatch(
setBoundingBoxDimensions({
...boundingBoxDimensions,
width: Math.floor(512),
})
);
};
return (
<IAISlider
label={t('parameters.width')}
min={64}
max={1024}
step={64}
value={boundingBoxDimensions.width}
onChange={handleChangeWidth}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetWidth}
/>
);
};
export default memo(ParamBoundingBoxWidth);

View File

@ -0,0 +1,33 @@
import { Flex, useDisclosure } from '@chakra-ui/react';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import IAICollapse from 'common/components/IAICollapse';
import ParamInfillMethod from './ParamInfillMethod';
import ParamInfillTilesize from './ParamInfillTilesize';
import ParamScaleBeforeProcessing from './ParamScaleBeforeProcessing';
import ParamScaledWidth from './ParamScaledWidth';
import ParamScaledHeight from './ParamScaledHeight';
const ParamInfillCollapse = () => {
const { t } = useTranslation();
const { isOpen, onToggle } = useDisclosure();
return (
<IAICollapse
label={t('parameters.boundingBoxHeader')}
isOpen={isOpen}
onToggle={onToggle}
>
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamInfillMethod />
<ParamInfillTilesize />
<ParamScaleBeforeProcessing />
<ParamScaledWidth />
<ParamScaledHeight />
</Flex>
</IAICollapse>
);
};
export default memo(ParamInfillCollapse);

View File

@ -0,0 +1,49 @@
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 { 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 { useTranslation } from 'react-i18next';
const selector = createSelector(
[generationSelector, systemSelector],
(parameters, system) => {
const { infillMethod } = parameters;
const { infillMethods } = system;
return {
infillMethod,
infillMethods,
};
},
defaultSelectorOptions
);
const ParamInfillMethod = () => {
const dispatch = useAppDispatch();
const { infillMethod, infillMethods } = useAppSelector(selector);
const { t } = useTranslation();
const handleChange = useCallback(
(e: ChangeEvent<HTMLSelectElement>) => {
dispatch(setInfillMethod(e.target.value));
},
[dispatch]
);
return (
<IAISelect
label={t('parameters.infillMethod')}
value={infillMethod}
validValues={infillMethods}
onChange={handleChange}
/>
);
};
export default memo(ParamInfillMethod);

View File

@ -0,0 +1,58 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { setTileSize } from 'features/parameters/store/generationSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
[generationSelector],
(parameters) => {
const { tileSize, infillMethod } = parameters;
return {
tileSize,
infillMethod,
};
},
defaultSelectorOptions
);
const ParamInfillTileSize = () => {
const dispatch = useAppDispatch();
const { tileSize, infillMethod } = useAppSelector(selector);
const { t } = useTranslation();
const handleChange = useCallback(
(v: number) => {
dispatch(setTileSize(v));
},
[dispatch]
);
const handleReset = useCallback(() => {
dispatch(setTileSize(32));
}, [dispatch]);
return (
<IAISlider
isDisabled={infillMethod !== 'tile'}
label={t('parameters.tileSize')}
min={16}
max={64}
sliderNumberInputProps={{ max: 256 }}
value={tileSize}
onChange={handleChange}
withInput
withSliderMarks
withReset
handleReset={handleReset}
/>
);
};
export default memo(ParamInfillTileSize);

View File

@ -0,0 +1,49 @@
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 { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setBoundingBoxScaleMethod } from 'features/canvas/store/canvasSlice';
import {
BoundingBoxScale,
BOUNDING_BOX_SCALES_DICT,
} from 'features/canvas/store/canvasTypes';
import { ChangeEvent, memo } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
[canvasSelector],
(canvas) => {
const { boundingBoxScaleMethod: boundingBoxScale } = canvas;
return {
boundingBoxScale,
};
},
defaultSelectorOptions
);
const ParamScaleBeforeProcessing = () => {
const dispatch = useAppDispatch();
const { boundingBoxScale } = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeBoundingBoxScaleMethod = (
e: ChangeEvent<HTMLSelectElement>
) => {
dispatch(setBoundingBoxScaleMethod(e.target.value as BoundingBoxScale));
};
return (
<IAISelect
label={t('parameters.scaleBeforeProcessing')}
validValues={BOUNDING_BOX_SCALES_DICT}
value={boundingBoxScale}
onChange={handleChangeBoundingBoxScaleMethod}
/>
);
};
export default memo(ParamScaleBeforeProcessing);

View File

@ -0,0 +1,68 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { systemSelector } from 'features/system/store/systemSelectors';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
[generationSelector, systemSelector, canvasSelector],
(parameters, system, canvas) => {
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = canvas;
return {
scaledBoundingBoxDimensions,
isManual: boundingBoxScaleMethod === 'manual',
};
},
defaultSelectorOptions
);
const ParamScaledHeight = () => {
const dispatch = useAppDispatch();
const { isManual, scaledBoundingBoxDimensions } = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeScaledHeight = (v: number) => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
height: Math.floor(v),
})
);
};
const handleResetScaledHeight = () => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
height: Math.floor(512),
})
);
};
return (
<IAISlider
isDisabled={!isManual}
label={t('parameters.scaledHeight')}
min={64}
max={1024}
step={64}
value={scaledBoundingBoxDimensions.height}
onChange={handleChangeScaledHeight}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetScaledHeight}
/>
);
};
export default memo(ParamScaledHeight);

View File

@ -0,0 +1,66 @@
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISlider from 'common/components/IAISlider';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const selector = createSelector(
[canvasSelector],
(canvas) => {
const { boundingBoxScaleMethod, scaledBoundingBoxDimensions } = canvas;
return {
scaledBoundingBoxDimensions,
isManual: boundingBoxScaleMethod === 'manual',
};
},
defaultSelectorOptions
);
const ParamScaledWidth = () => {
const dispatch = useAppDispatch();
const { isManual, scaledBoundingBoxDimensions } = useAppSelector(selector);
const { t } = useTranslation();
const handleChangeScaledWidth = (v: number) => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
width: Math.floor(v),
})
);
};
const handleResetScaledWidth = () => {
dispatch(
setScaledBoundingBoxDimensions({
...scaledBoundingBoxDimensions,
width: Math.floor(512),
})
);
};
return (
<IAISlider
isDisabled={!isManual}
label={t('parameters.scaledWidth')}
min={64}
max={1024}
step={64}
value={scaledBoundingBoxDimensions.width}
onChange={handleChangeScaledWidth}
sliderNumberInputProps={{ max: 4096 }}
withSliderMarks
withInput
inputReadOnly
withReset
handleReset={handleResetScaledWidth}
/>
);
};
export default memo(ParamScaledWidth);

View File

@ -0,0 +1,28 @@
import ParamSeamBlur from './ParamSeamBlur';
import ParamSeamSize from './ParamSeamSize';
import ParamSeamSteps from './ParamSeamSteps';
import ParamSeamStrength from './ParamSeamStrength';
import { useDisclosure } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import IAICollapse from 'common/components/IAICollapse';
import { memo } from 'react';
const ParamSeamCorrectionCollapse = () => {
const { t } = useTranslation();
const { isOpen, onToggle } = useDisclosure();
return (
<IAICollapse
label={t('parameters.seamCorrectionHeader')}
isOpen={isOpen}
onToggle={onToggle}
>
<ParamSeamSize />
<ParamSeamBlur />
<ParamSeamStrength />
<ParamSeamSteps />
</IAICollapse>
);
};
export default memo(ParamSeamCorrectionCollapse);

View File

@ -6,7 +6,7 @@ import { setSampler } from 'features/parameters/store/generationSlice';
import { ChangeEvent, memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const ParamScheduler = () => {
const ParamSampler = () => {
const sampler = useAppSelector(
(state: RootState) => state.generation.sampler
);
@ -29,4 +29,4 @@ const ParamScheduler = () => {
);
};
export default memo(ParamScheduler);
export default memo(ParamSampler);

View File

@ -1,18 +0,0 @@
import { VStack } from '@chakra-ui/react';
import ParamSeamlessToggle from './Seamless/ParamSeamlessToggle';
// import ParamSeamlessAxes from '../../Parameters/Seamless/ParamSeamlessAxes';
import { ParamHiresToggle } from './Hires/ParamHiresToggle';
import { ParamHiresStrength } from './Hires/ParamHiresStrength';
const OtherSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<ParamSeamlessToggle />
{/* <ParamSeamlessAxes /> */}
<ParamHiresToggle />
<ParamHiresStrength />
</VStack>
);
};
export default OtherSettings;

View File

@ -1,94 +0,0 @@
import { Accordion } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { Feature } from 'app/features';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { tabMap } from 'features/ui/store/tabMap';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { openAccordionItemsChanged } from 'features/ui/store/uiSlice';
import { map } from 'lodash-es';
import { ReactNode, useCallback } from 'react';
import InvokeAccordionItem from './AccordionItems/InvokeAccordionItem';
const parametersAccordionSelector = createSelector([uiSelector], (uiSlice) => {
const {
activeTab,
openLinearAccordionItems,
openUnifiedCanvasAccordionItems,
} = uiSlice;
let openAccordions: number[] = [];
if (tabMap[activeTab] === 'generate') {
openAccordions = openLinearAccordionItems;
}
if (tabMap[activeTab] === 'unifiedCanvas') {
openAccordions = openUnifiedCanvasAccordionItems;
}
return {
openAccordions,
};
});
export type ParametersAccordionItem = {
name: string;
header: string;
content: ReactNode;
feature?: Feature;
additionalHeaderComponents?: ReactNode;
};
export type ParametersAccordionItems = {
[parametersAccordionKey: string]: ParametersAccordionItem;
};
type ParametersAccordionProps = {
accordionItems: ParametersAccordionItems;
};
/**
* Main container for generation and processing parameters.
*/
const ParametersAccordion = ({ accordionItems }: ParametersAccordionProps) => {
const { openAccordions } = useAppSelector(parametersAccordionSelector);
const dispatch = useAppDispatch();
const handleChangeAccordionState = (openAccordions: number | number[]) => {
dispatch(
openAccordionItemsChanged(
Array.isArray(openAccordions) ? openAccordions : [openAccordions]
)
);
};
// Render function for accordion items
const renderAccordionItems = useCallback(
() =>
map(accordionItems, (accordionItem) => (
<InvokeAccordionItem
key={accordionItem.name}
accordionItem={accordionItem}
/>
)),
[accordionItems]
);
return (
<Accordion
defaultIndex={openAccordions}
allowMultiple
onChange={handleChangeAccordionState}
sx={{
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
{renderAccordionItems()}
</Accordion>
);
};
export default ParametersAccordion;

View File

@ -14,10 +14,10 @@ import {
import { setShouldShowParametersPanel } from 'features/ui/store/uiSlice';
import ResizableDrawer from './common/ResizableDrawer/ResizableDrawer';
import PinParametersPanelButton from './PinParametersPanelButton';
import TextTabParametersDrawer from './tabs/text/TextTabParametersDrawer';
import TextTabParameters from './tabs/text/TextTabParameters';
import ImageTabParameters from './tabs/image/ImageTabParameters';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import UnifiedCanvasParameters from './tabs/UnifiedCanvas/UnifiedCanvasParameters';
const selector = createSelector(
[uiSelector, activeTabNameSelector, lightboxSelector],
@ -59,18 +59,26 @@ const ParametersDrawer = () => {
}
if (activeTabName === 'unifiedCanvas') {
return null;
return <UnifiedCanvasParameters />;
}
return null;
}, [activeTabName]);
if (shouldPinParametersPanel) {
return null;
}
return (
<ResizableDrawer
direction="left"
isResizable={false}
isOpen={shouldShowParametersPanel && !shouldPinParametersPanel}
isOpen={shouldShowParametersPanel}
onClose={handleClosePanel}
>
<Flex flexDir="column" position="relative" h="full" w="full">
<Flex
sx={{ flexDir: 'column', h: 'full', w: PARAMETERS_PANEL_WIDTH, gap: 2 }}
>
<Flex
paddingTop={1.5}
paddingBottom={4}
@ -81,9 +89,7 @@ const ParametersDrawer = () => {
<PinParametersPanelButton />
</Flex>
<OverlayScrollable>
<Box sx={{ h: 'full', w: PARAMETERS_PANEL_WIDTH }}>
{drawerContent}
</Box>
<Flex sx={{ flexDir: 'column', gap: 2 }}>{drawerContent}</Flex>
</OverlayScrollable>
</Flex>
</ResizableDrawer>

View File

@ -0,0 +1,39 @@
import { Box, Flex } from '@chakra-ui/react';
import { PropsWithChildren, memo } from 'react';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import OverlayScrollable from './common/OverlayScrollable';
import PinParametersPanelButton from './PinParametersPanelButton';
type ParametersPinnedWrapperProps = PropsWithChildren;
const ParametersPinnedWrapper = (props: ParametersPinnedWrapperProps) => {
return (
<Box
sx={{
position: 'relative',
h: 'full',
w: PARAMETERS_PANEL_WIDTH,
flexShrink: 0,
}}
>
<OverlayScrollable>
<Flex
sx={{
gap: 2,
flexDirection: 'column',
h: 'full',
w: 'full',
position: 'absolute',
}}
>
{props.children}
</Flex>
</OverlayScrollable>
<PinParametersPanelButton
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
/>
</Box>
);
};
export default memo(ParametersPinnedWrapper);

View File

@ -5,7 +5,7 @@ const OverlayScrollable = (props: PropsWithChildren) => {
return (
<OverlayScrollbarsComponent
defer
style={{ height: '100%' }}
style={{ height: '100%', width: '100%' }}
options={{
scrollbars: {
visibility: 'auto',

View File

@ -1,6 +1,5 @@
import { Box, Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
// import IAICanvas from 'features/canvas/components/IAICanvas';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAICanvas from 'features/canvas/components/IAICanvas';
import IAICanvasResizer from 'features/canvas/components/IAICanvasResizer';
@ -9,7 +8,7 @@ import { canvasSelector } from 'features/canvas/store/canvasSelectors';
import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale';
import { isEqual } from 'lodash-es';
import { useLayoutEffect } from 'react';
import { memo, useLayoutEffect } from 'react';
const selector = createSelector(
[canvasSelector],
@ -80,4 +79,4 @@ const UnifiedCanvasContent = () => {
);
};
export default UnifiedCanvasContent;
export default memo(UnifiedCanvasContent);

View File

@ -0,0 +1,83 @@
import { memo } from 'react';
import { Box, Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import ModelSelect from 'features/system/components/ModelSelect';
import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations';
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale';
import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth';
import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight';
import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength';
import ImageToImageFit from 'features/parameters/components/Parameters/ImageToImage/ImageToImageFit';
import ParamSampler from 'features/parameters/components/Parameters/Core/ParamSampler';
const selector = createSelector(
uiSelector,
(ui) => {
const { shouldUseSliders } = ui;
return { shouldUseSliders };
},
defaultSelectorOptions
);
const UnifiedCanvasCoreParameters = () => {
const { shouldUseSliders } = useAppSelector(selector);
return (
<Flex
sx={{
flexDirection: 'column',
gap: 2,
bg: 'base.800',
p: 4,
borderRadius: 'base',
}}
>
{shouldUseSliders ? (
<Flex sx={{ gap: 3, flexDirection: 'column' }}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<ImageToImageStrength />
<ImageToImageFit />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamSampler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</Flex>
) : (
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<Flex gap={3}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamSampler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
<ImageToImageStrength />
<ImageToImageFit />
</Flex>
)}
</Flex>
);
};
export default memo(UnifiedCanvasCoreParameters);

View File

@ -1,101 +1,30 @@
import { Flex } from '@chakra-ui/react';
import { Feature } from 'app/features';
import BoundingBoxSettings from 'features/parameters/components/AdvancedParameters/Canvas/BoundingBox/BoundingBoxSettings';
import InfillAndScalingSettings from 'features/parameters/components/AdvancedParameters/Canvas/InfillAndScalingSettings';
import SeamCorrectionSettings from 'features/parameters/components/AdvancedParameters/Canvas/SeamCorrection/SeamCorrectionSettings';
import ImageToImageStrength from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength';
import MainSettings from 'features/parameters/components/MainParameters/MainSettings';
import ParametersAccordion, {
ParametersAccordionItems,
} from 'features/parameters/components/ParametersAccordion';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import { useTranslation } from 'react-i18next';
import OverlayScrollable from '../../common/OverlayScrollable';
// import ParamSeedSettings from 'features/parameters/components/Parameters/Seed/ParamSeedSettings';
// import ParamVariationSettings from 'features/parameters/components/Parameters/Variations/ParamVariationSettings';
// import ParamSymmetrySettings from 'features/parameters/components/Parameters/Symmetry/ParamSymmetrySettings';
// import ParamVariationToggle from 'features/parameters/components/Parameters/Variations/ParamVariationToggle';
// import ParamSymmetryToggle from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryToggle';
import ParamPositiveConditioning from 'features/parameters/components/Parameters/ParamPositiveConditioning';
import ParamNegativeConditioning from 'features/parameters/components/Parameters/ParamNegativeConditioning';
import ParamSeedCollapse from 'features/parameters/components/Parameters/Seed/ParamSeedCollapse';
import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse';
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
import ParamBoundingBoxCollapse from 'features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxCollapse';
import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse';
import ParamSeamCorrectionCollapse from 'features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse';
import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters';
import { memo } from 'react';
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
export default function UnifiedCanvasParameters() {
const { t } = useTranslation();
const unifiedCanvasAccordions: ParametersAccordionItems = {
general: {
name: 'general',
header: `${t('parameters.general')}`,
feature: undefined,
content: <MainSettings />,
},
unifiedCanvasImg2Img: {
name: 'unifiedCanvasImg2Img',
header: `${t('parameters.imageToImage')}`,
feature: undefined,
content: <ImageToImageStrength />,
},
// seed: {
// name: 'seed',
// header: `${t('parameters.seed')}`,
// feature: Feature.SEED,
// content: <ParamSeedSettings />,
// },
boundingBox: {
name: 'boundingBox',
header: `${t('parameters.boundingBoxHeader')}`,
feature: Feature.BOUNDING_BOX,
content: <BoundingBoxSettings />,
},
seamCorrection: {
name: 'seamCorrection',
header: `${t('parameters.seamCorrectionHeader')}`,
feature: Feature.SEAM_CORRECTION,
content: <SeamCorrectionSettings />,
},
infillAndScaling: {
name: 'infillAndScaling',
header: `${t('parameters.infillScalingHeader')}`,
feature: Feature.INFILL_AND_SCALING,
content: <InfillAndScalingSettings />,
},
// variations: {
// name: 'variations',
// header: `${t('parameters.variations')}`,
// feature: Feature.VARIATIONS,
// content: <ParamVariationSettings />,
// additionalHeaderComponents: <ParamVariationToggle />,
// },
// symmetry: {
// name: 'symmetry',
// header: `${t('parameters.symmetry')}`,
// content: <ParamSymmetrySettings />,
// additionalHeaderComponents: <ParamSymmetryToggle />,
// },
};
const UnifiedCanvasParameters = () => {
return (
<OverlayScrollable>
<Flex
sx={{
gap: 2,
flexDirection: 'column',
h: 'full',
w: 'full',
position: 'absolute',
}}
>
<ParamPositiveConditioning />
<ParamNegativeConditioning />
<ProcessButtons />
<ParamSeedCollapse />
<ParamVariationCollapse />
<ParamSymmetryCollapse />
<ParametersAccordion accordionItems={unifiedCanvasAccordions} />
</Flex>
</OverlayScrollable>
<>
<ParamPositiveConditioning />
<ParamNegativeConditioning />
<ProcessButtons />
<UnifiedCanvasCoreParameters />
<ParamSeedCollapse />
<ParamVariationCollapse />
<ParamSymmetryCollapse />
<ParamBoundingBoxCollapse />
<ParamSeamCorrectionCollapse />
<ParamInfillAndScalingCollapse />
</>
);
}
};
export default memo(UnifiedCanvasParameters);

View File

@ -1,4 +1,4 @@
import { TabPanel } from '@chakra-ui/react';
import { Box, Flex, TabPanel } from '@chakra-ui/react';
import { memo } from 'react';
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
import PinParametersPanelButton from '../../PinParametersPanelButton';
@ -11,6 +11,8 @@ import UnifiedCanvasContent from './UnifiedCanvasContent';
import ResizeHandle from '../ResizeHandle';
import UnifiedCanvasParameters from './UnifiedCanvasParameters';
import UnifiedCanvasContentBeta from './UnifiedCanvasBeta/UnifiedCanvasContentBeta';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
const selector = createSelector(uiSelector, (ui) => {
const {
@ -41,42 +43,18 @@ const UnifiedCanvasTab = () => {
} = useAppSelector(selector);
return (
<PanelGroup
autoSaveId="canvasTab"
direction="horizontal"
style={{ height: '100%', width: '100%' }}
>
<Flex sx={{ gap: 4, w: 'full', h: 'full' }}>
{shouldPinParametersPanel && shouldShowParametersPanel && (
<>
<Panel
id="canvasTab_parameters"
order={0}
defaultSize={30}
minSize={20}
style={{ position: 'relative' }}
>
<UnifiedCanvasParameters />
<PinParametersPanelButton
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
/>
</Panel>
<ResizeHandle />
</>
<ParametersPinnedWrapper>
<UnifiedCanvasParameters />
</ParametersPinnedWrapper>
)}
<Panel
order={1}
minSize={30}
onResize={() => {
dispatch(requestCanvasRescale());
}}
>
{shouldUseCanvasBetaLayout ? (
<UnifiedCanvasContentBeta />
) : (
<UnifiedCanvasContent />
)}
</Panel>
</PanelGroup>
{shouldUseCanvasBetaLayout ? (
<UnifiedCanvasContentBeta />
) : (
<UnifiedCanvasContent />
)}
</Flex>
);
};

View File

@ -14,10 +14,10 @@ import ResizeHandle from '../ResizeHandle';
import ImageTabParameters from './ImageTabParameters';
import ImageTabImageParameters from './ImageTabImageParameters';
import TextTabMain from '../text/TextTabMain';
import InitialImagePreview from 'features/parameters/components/AdvancedParameters/ImageToImage/InitialImagePreview';
import InitialImageDisplay from 'features/parameters/components/AdvancedParameters/ImageToImage/InitialImageDisplay';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import { ImperativePanelGroupHandle } from 'react-resizable-panels';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
import InitialImageDisplay from 'features/parameters/components/Parameters/ImageToImage/InitialImageDisplay';
const selector = createSelector(uiSelector, (ui) => {
const {
@ -60,19 +60,9 @@ const TextTab = () => {
return (
<Flex sx={{ gap: 4, w: 'full', h: 'full' }}>
{shouldPinParametersPanel && shouldShowParametersPanel && (
<Box
sx={{
position: 'relative',
h: 'full',
w: PARAMETERS_PANEL_WIDTH,
flexShrink: 0,
}}
>
<ParametersPinnedWrapper>
<ImageTabParameters />
<PinParametersPanelButton
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
/>
</Box>
</ParametersPinnedWrapper>
)}
<Box sx={{ w: 'full', h: 'full' }}>
<PanelGroup

View File

@ -0,0 +1,83 @@
import { memo } from 'react';
import { Box, Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations';
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale';
import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth';
import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight';
import ParamSampler from 'features/parameters/components/Parameters/Core/ParamSampler';
import ModelSelect from 'features/system/components/ModelSelect';
import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength';
import ImageToImageFit from 'features/parameters/components/Parameters/ImageToImage/ImageToImageFit';
const selector = createSelector(
uiSelector,
(ui) => {
const { shouldUseSliders } = ui;
return { shouldUseSliders };
},
defaultSelectorOptions
);
const ImageTabCoreParameters = () => {
const { shouldUseSliders } = useAppSelector(selector);
return (
<Flex
sx={{
flexDirection: 'column',
gap: 2,
bg: 'base.800',
p: 4,
borderRadius: 'base',
}}
>
{shouldUseSliders ? (
<Flex sx={{ gap: 3, flexDirection: 'column' }}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<ImageToImageStrength />
<ImageToImageFit />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamSampler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</Flex>
) : (
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<Flex gap={3}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamSampler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
<ImageToImageStrength />
<ImageToImageFit />
</Flex>
)}
</Flex>
);
};
export default memo(ImageTabCoreParameters);

View File

@ -1,112 +1,27 @@
import { Box, Flex } from '@chakra-ui/react';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import { memo } from 'react';
import OverlayScrollable from '../../common/OverlayScrollable';
import ParamPositiveConditioning from 'features/parameters/components/Parameters/ParamPositiveConditioning';
import ParamNegativeConditioning from 'features/parameters/components/Parameters/ParamNegativeConditioning';
import { createSelector } from '@reduxjs/toolkit';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import ParamIterations from 'features/parameters/components/Parameters/ParamIterations';
import ParamSteps from 'features/parameters/components/Parameters/ParamSteps';
import ParamCFGScale from 'features/parameters/components/Parameters/ParamCFGScale';
import ParamWidth from 'features/parameters/components/Parameters/ParamWidth';
import ParamHeight from 'features/parameters/components/Parameters/ParamHeight';
import ParamScheduler from 'features/parameters/components/Parameters/ParamScheduler';
import ModelSelect from 'features/system/components/ModelSelect';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
import ParamSeedCollapse from 'features/parameters/components/Parameters/Seed/ParamSeedCollapse';
import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse';
import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse';
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
import ParamHiresCollapse from 'features/parameters/components/Parameters/Hires/ParamHiresCollapse';
import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse';
import ImageToImageStrength from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageStrength';
import ImageToImageFit from 'features/parameters/components/AdvancedParameters/ImageToImage/ImageToImageFit';
const selector = createSelector(
uiSelector,
(ui) => {
const { shouldUseSliders } = ui;
return { shouldUseSliders };
},
defaultSelectorOptions
);
import ImageTabCoreParameters from './ImageTabCoreParameters';
const ImageTabParameters = () => {
const { shouldUseSliders } = useAppSelector(selector);
return (
<OverlayScrollable>
<Flex
sx={{
gap: 2,
flexDirection: 'column',
h: 'full',
w: 'full',
position: 'absolute',
}}
>
<ParamPositiveConditioning />
<ParamNegativeConditioning />
<ProcessButtons />
<Flex
sx={{
flexDirection: 'column',
gap: 2,
bg: 'base.800',
p: 4,
borderRadius: 'base',
}}
>
{shouldUseSliders ? (
<Flex sx={{ gap: 3, flexDirection: 'column' }}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<ImageToImageStrength />
<ImageToImageFit />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</Flex>
) : (
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<Flex gap={3}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
<ImageToImageStrength />
<ImageToImageFit />
</Flex>
)}
</Flex>
<ParamSeedCollapse />
<ParamVariationCollapse />
<ParamNoiseCollapse />
<ParamSymmetryCollapse />
<ParamSeamlessCollapse />
</Flex>
</OverlayScrollable>
<>
<ParamPositiveConditioning />
<ParamNegativeConditioning />
<ProcessButtons />
<ImageTabCoreParameters />
<ParamSeedCollapse />
<ParamVariationCollapse />
<ParamNoiseCollapse />
<ParamSymmetryCollapse />
<ParamSeamlessCollapse />
</>
);
};

View File

@ -10,6 +10,7 @@ import TextTabMain from './TextTabMain';
import ResizeHandle from '../ResizeHandle';
import TextTabParameters from './TextTabParameters';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
import ParametersPinnedWrapper from '../../ParametersPinnedWrapper';
const selector = createSelector(uiSelector, (ui) => {
const {
@ -42,19 +43,9 @@ const TextTab = () => {
return (
<Flex sx={{ gap: 4, w: 'full', h: 'full' }}>
{shouldPinParametersPanel && shouldShowParametersPanel && (
<Box
sx={{
position: 'relative',
h: 'full',
// w: PARAMETERS_PANEL_WIDTH,
flexShrink: 0,
}}
>
<ParametersPinnedWrapper>
<TextTabParameters />
<PinParametersPanelButton
sx={{ position: 'absolute', top: 0, insetInlineEnd: 0 }}
/>
</Box>
</ParametersPinnedWrapper>
)}
<TextTabMain />
</Flex>

View File

@ -0,0 +1,77 @@
import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations';
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale';
import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth';
import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight';
import ParamSampler from 'features/parameters/components/Parameters/Core/ParamSampler';
import ModelSelect from 'features/system/components/ModelSelect';
import { Box, Flex } from '@chakra-ui/react';
import { useAppSelector } from 'app/store/storeHooks';
import { createSelector } from '@reduxjs/toolkit';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { memo } from 'react';
const selector = createSelector(
uiSelector,
(ui) => {
const { shouldUseSliders } = ui;
return { shouldUseSliders };
},
defaultSelectorOptions
);
const TextTabCoreParameters = () => {
const { shouldUseSliders } = useAppSelector(selector);
return (
<Flex
sx={{
flexDirection: 'column',
gap: 2,
bg: 'base.800',
p: 4,
borderRadius: 'base',
}}
>
{shouldUseSliders ? (
<Flex sx={{ gap: 3, flexDirection: 'column' }}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamSampler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</Flex>
) : (
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<Flex gap={3}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamSampler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
<ParamWidth />
<ParamHeight />
</Flex>
)}
</Flex>
);
};
export default memo(TextTabCoreParameters);

View File

@ -1,107 +1,29 @@
import { Box, Flex } from '@chakra-ui/react';
import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons';
import { memo } from 'react';
import OverlayScrollable from '../../common/OverlayScrollable';
import ParamPositiveConditioning from 'features/parameters/components/Parameters/ParamPositiveConditioning';
import ParamNegativeConditioning from 'features/parameters/components/Parameters/ParamNegativeConditioning';
import { createSelector } from '@reduxjs/toolkit';
import { uiSelector } from 'features/ui/store/uiSelectors';
import { useAppSelector } from 'app/store/storeHooks';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import ParamIterations from 'features/parameters/components/Parameters/ParamIterations';
import ParamSteps from 'features/parameters/components/Parameters/ParamSteps';
import ParamCFGScale from 'features/parameters/components/Parameters/ParamCFGScale';
import ParamWidth from 'features/parameters/components/Parameters/ParamWidth';
import ParamHeight from 'features/parameters/components/Parameters/ParamHeight';
import ParamScheduler from 'features/parameters/components/Parameters/ParamScheduler';
import ModelSelect from 'features/system/components/ModelSelect';
import ParamPositiveConditioning from 'features/parameters/components/Parameters/Core/ParamPositiveConditioning';
import ParamNegativeConditioning from 'features/parameters/components/Parameters/Core/ParamNegativeConditioning';
import ParamSeedCollapse from 'features/parameters/components/Parameters/Seed/ParamSeedCollapse';
import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse';
import ParamNoiseCollapse from 'features/parameters/components/Parameters/Noise/ParamNoiseCollapse';
import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse';
import ParamHiresCollapse from 'features/parameters/components/Parameters/Hires/ParamHiresCollapse';
import ParamSeamlessCollapse from 'features/parameters/components/Parameters/Seamless/ParamSeamlessCollapse';
import { PARAMETERS_PANEL_WIDTH } from 'theme/util/constants';
const selector = createSelector(
uiSelector,
(ui) => {
const { shouldUseSliders } = ui;
return { shouldUseSliders };
},
defaultSelectorOptions
);
import TextTabCoreParameters from './TextTabCoreParameters';
const TextTabParameters = () => {
const { shouldUseSliders } = useAppSelector(selector);
return (
<OverlayScrollable>
<Flex
sx={{
gap: 2,
flexDirection: 'column',
h: 'full',
w: 'full',
}}
>
<ParamPositiveConditioning />
<ParamNegativeConditioning />
<ProcessButtons />
<Flex
sx={{
flexDirection: 'column',
gap: 2,
bg: 'base.800',
p: 4,
borderRadius: 'base',
}}
>
{shouldUseSliders ? (
<Flex sx={{ gap: 3, flexDirection: 'column' }}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
</Flex>
) : (
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<Flex gap={3}>
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<Flex gap={3} w="full">
<Box flexGrow={2}>
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
</Box>
</Flex>
<ParamWidth />
<ParamHeight />
</Flex>
)}
</Flex>
<ParamSeedCollapse />
<ParamVariationCollapse />
<ParamNoiseCollapse />
<ParamSymmetryCollapse />
<ParamHiresCollapse />
<ParamSeamlessCollapse />
</Flex>
</OverlayScrollable>
<>
<ParamPositiveConditioning />
<ParamNegativeConditioning />
<ProcessButtons />
<TextTabCoreParameters />
<ParamSeedCollapse />
<ParamVariationCollapse />
<ParamNoiseCollapse />
<ParamSymmetryCollapse />
<ParamHiresCollapse />
<ParamSeamlessCollapse />
</>
);
};