mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): improve accordion ux (#3647)
- Accordions now may be opened or closed regardless of whether or not their contents are enabled or active - Accordions have a short text indicator alerting the user if their contents are enabled, either a simple `Enabled` or, for accordions like LoRA or ControlNet, `X Active` if any are active https://github.com/invoke-ai/InvokeAI/assets/4822129/43db63bd-7ef3-43f2-8dad-59fc7200af2e
This commit is contained in:
commit
07d7959dc0
@ -4,22 +4,25 @@ import {
|
||||
Collapse,
|
||||
Flex,
|
||||
Spacer,
|
||||
Switch,
|
||||
Text,
|
||||
useColorMode,
|
||||
useDisclosure,
|
||||
} from '@chakra-ui/react';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import { PropsWithChildren, memo } from 'react';
|
||||
import { mode } from 'theme/util/mode';
|
||||
|
||||
export type IAIToggleCollapseProps = PropsWithChildren & {
|
||||
label: string;
|
||||
isOpen: boolean;
|
||||
onToggle: () => void;
|
||||
withSwitch?: boolean;
|
||||
activeLabel?: string;
|
||||
defaultIsOpen?: boolean;
|
||||
};
|
||||
|
||||
const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
const { label, isOpen, onToggle, children, withSwitch = false } = props;
|
||||
const { label, activeLabel, children, defaultIsOpen = false } = props;
|
||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen });
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Flex
|
||||
@ -28,6 +31,7 @@ const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
alignItems: 'center',
|
||||
p: 2,
|
||||
px: 4,
|
||||
gap: 2,
|
||||
borderTopRadius: 'base',
|
||||
borderBottomRadius: isOpen ? 0 : 'base',
|
||||
bg: isOpen
|
||||
@ -48,9 +52,31 @@ const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
<AnimatePresence>
|
||||
{activeLabel && (
|
||||
<motion.div
|
||||
key="statusText"
|
||||
initial={{
|
||||
opacity: 0,
|
||||
}}
|
||||
animate={{
|
||||
opacity: 1,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.1 },
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
sx={{ color: 'accent.500', _dark: { color: 'accent.300' } }}
|
||||
>
|
||||
{activeLabel}
|
||||
</Text>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<Spacer />
|
||||
{withSwitch && <Switch isChecked={isOpen} pointerEvents="none" />}
|
||||
{!withSwitch && (
|
||||
<ChevronUpIcon
|
||||
sx={{
|
||||
w: '1rem',
|
||||
@ -60,7 +86,6 @@ const IAICollapse = (props: IAIToggleCollapseProps) => {
|
||||
transitionDuration: 'normal',
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
<Collapse in={isOpen} animateOpacity style={{ overflow: 'unset' }}>
|
||||
<Box
|
||||
|
@ -36,7 +36,6 @@ const IAISwitch = (props: Props) => {
|
||||
isDisabled={isDisabled}
|
||||
width={width}
|
||||
display="flex"
|
||||
gap={4}
|
||||
alignItems="center"
|
||||
{...formControlProps}
|
||||
>
|
||||
@ -47,6 +46,7 @@ const IAISwitch = (props: Props) => {
|
||||
sx={{
|
||||
cursor: isDisabled ? 'not-allowed' : 'pointer',
|
||||
...formLabelProps?.sx,
|
||||
pe: 4,
|
||||
}}
|
||||
{...formLabelProps}
|
||||
>
|
||||
|
@ -0,0 +1,36 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { isControlNetEnabledToggled } from 'features/controlNet/store/controlNetSlice';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { isEnabled } = state.controlNet;
|
||||
|
||||
return { isEnabled };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamControlNetFeatureToggle = () => {
|
||||
const { isEnabled } = useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleChange = useCallback(() => {
|
||||
dispatch(isControlNetEnabledToggled());
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label="Enable ControlNet"
|
||||
isChecked={isEnabled}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ParamControlNetFeatureToggle;
|
@ -0,0 +1,15 @@
|
||||
import { filter } from 'lodash-es';
|
||||
import { ControlNetConfig } from '../store/controlNetSlice';
|
||||
|
||||
export const getValidControlNets = (
|
||||
controlNets: Record<string, ControlNetConfig>
|
||||
) => {
|
||||
const validControlNets = filter(
|
||||
controlNets,
|
||||
(c) =>
|
||||
c.isEnabled &&
|
||||
(Boolean(c.processedControlImage) ||
|
||||
(c.processorType === 'none' && Boolean(c.controlImage)))
|
||||
);
|
||||
return validControlNets;
|
||||
};
|
@ -1,40 +1,30 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { useCallback } from 'react';
|
||||
import { isEnabledToggled } from '../store/slice';
|
||||
import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
|
||||
import ParamDynamicPromptsCombinatorial from './ParamDynamicPromptsCombinatorial';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import ParamDynamicPromptsToggle from './ParamDynamicPromptsEnabled';
|
||||
import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { isEnabled } = state.dynamicPrompts;
|
||||
|
||||
return { isEnabled };
|
||||
return { activeLabel: isEnabled ? 'Enabled' : undefined };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamDynamicPromptsCollapse = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { isEnabled } = useAppSelector(selector);
|
||||
|
||||
const handleToggleIsEnabled = useCallback(() => {
|
||||
dispatch(isEnabledToggled());
|
||||
}, [dispatch]);
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
isOpen={isEnabled}
|
||||
onToggle={handleToggleIsEnabled}
|
||||
label="Dynamic Prompts"
|
||||
withSwitch
|
||||
>
|
||||
<IAICollapse label="Dynamic Prompts" activeLabel={activeLabel}>
|
||||
<Flex sx={{ gap: 2, flexDir: 'column' }}>
|
||||
<ParamDynamicPromptsToggle />
|
||||
<ParamDynamicPromptsCombinatorial />
|
||||
<ParamDynamicPromptsMaxPrompts />
|
||||
</Flex>
|
||||
|
@ -1,23 +1,23 @@
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { combinatorialToggled } from '../store/slice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useCallback } from 'react';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { useCallback } from 'react';
|
||||
import { combinatorialToggled } from '../store/slice';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { combinatorial } = state.dynamicPrompts;
|
||||
const { combinatorial, isEnabled } = state.dynamicPrompts;
|
||||
|
||||
return { combinatorial };
|
||||
return { combinatorial, isDisabled: !isEnabled };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamDynamicPromptsCombinatorial = () => {
|
||||
const { combinatorial } = useAppSelector(selector);
|
||||
const { combinatorial, isDisabled } = useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleChange = useCallback(() => {
|
||||
@ -26,6 +26,7 @@ const ParamDynamicPromptsCombinatorial = () => {
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
isDisabled={isDisabled}
|
||||
label="Combinatorial Generation"
|
||||
isChecked={combinatorial}
|
||||
onChange={handleChange}
|
||||
|
@ -0,0 +1,36 @@
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { useCallback } from 'react';
|
||||
import { isEnabledToggled } from '../store/slice';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { isEnabled } = state.dynamicPrompts;
|
||||
|
||||
return { isEnabled };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamDynamicPromptsToggle = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { isEnabled } = useAppSelector(selector);
|
||||
|
||||
const handleToggleIsEnabled = useCallback(() => {
|
||||
dispatch(isEnabledToggled());
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label="Enable Dynamic Prompts"
|
||||
isChecked={isEnabled}
|
||||
onChange={handleToggleIsEnabled}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ParamDynamicPromptsToggle;
|
@ -1,25 +1,31 @@
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { maxPromptsChanged, maxPromptsReset } from '../store/slice';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { useCallback } from 'react';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { useCallback } from 'react';
|
||||
import { maxPromptsChanged, maxPromptsReset } from '../store/slice';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { maxPrompts, combinatorial } = state.dynamicPrompts;
|
||||
const { maxPrompts, combinatorial, isEnabled } = state.dynamicPrompts;
|
||||
const { min, sliderMax, inputMax } =
|
||||
state.config.sd.dynamicPrompts.maxPrompts;
|
||||
|
||||
return { maxPrompts, min, sliderMax, inputMax, combinatorial };
|
||||
return {
|
||||
maxPrompts,
|
||||
min,
|
||||
sliderMax,
|
||||
inputMax,
|
||||
isDisabled: !isEnabled || !combinatorial,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamDynamicPromptsMaxPrompts = () => {
|
||||
const { maxPrompts, min, sliderMax, inputMax, combinatorial } =
|
||||
const { maxPrompts, min, sliderMax, inputMax, isDisabled } =
|
||||
useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@ -37,7 +43,7 @@ const ParamDynamicPromptsMaxPrompts = () => {
|
||||
return (
|
||||
<IAISlider
|
||||
label="Max Prompts"
|
||||
isDisabled={!combinatorial}
|
||||
isDisabled={isDisabled}
|
||||
min={min}
|
||||
max={sliderMax}
|
||||
value={maxPrompts}
|
||||
|
@ -1,14 +1,30 @@
|
||||
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { size } from 'lodash-es';
|
||||
import { memo } from 'react';
|
||||
import ParamLoraList from './ParamLoraList';
|
||||
import ParamLoraSelect from './ParamLoraSelect';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const loraCount = size(state.lora.loras);
|
||||
return {
|
||||
activeLabel: loraCount > 0 ? `${loraCount} Active` : undefined,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamLoraCollapse = () => {
|
||||
const { isOpen, onToggle } = useDisclosure();
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
return (
|
||||
<IAICollapse label="LoRAs" isOpen={isOpen} onToggle={onToggle}>
|
||||
<IAICollapse label={'LoRA'} activeLabel={activeLabel}>
|
||||
<Flex sx={{ flexDir: 'column', gap: 2 }}>
|
||||
<ParamLoraSelect />
|
||||
<ParamLoraList />
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { filter } from 'lodash-es';
|
||||
import { getValidControlNets } from 'features/controlNet/util/getValidControlNets';
|
||||
import { CollectInvocation, ControlNetInvocation } from 'services/api/types';
|
||||
import { NonNullableGraph } from '../types/types';
|
||||
import { CONTROL_NET_COLLECT } from './graphBuilders/constants';
|
||||
@ -11,13 +11,7 @@ export const addControlNetToLinearGraph = (
|
||||
): void => {
|
||||
const { isEnabled: isControlNetEnabled, controlNets } = state.controlNet;
|
||||
|
||||
const validControlNets = filter(
|
||||
controlNets,
|
||||
(c) =>
|
||||
c.isEnabled &&
|
||||
(Boolean(c.processedControlImage) ||
|
||||
(c.processorType === 'none' && Boolean(c.controlImage)))
|
||||
);
|
||||
const validControlNets = getValidControlNets(controlNets);
|
||||
|
||||
if (isControlNetEnabled && Boolean(validControlNets.length)) {
|
||||
if (validControlNets.length > 1) {
|
||||
|
@ -1,20 +1,15 @@
|
||||
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { memo } from 'react';
|
||||
import ParamBoundingBoxWidth from './ParamBoundingBoxWidth';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ParamBoundingBoxHeight from './ParamBoundingBoxHeight';
|
||||
import ParamBoundingBoxWidth from './ParamBoundingBoxWidth';
|
||||
|
||||
const ParamBoundingBoxCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const { isOpen, onToggle } = useDisclosure();
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.boundingBoxHeader')}
|
||||
isOpen={isOpen}
|
||||
onToggle={onToggle}
|
||||
>
|
||||
<IAICollapse label={t('parameters.boundingBoxHeader')}>
|
||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
||||
<ParamBoundingBoxWidth />
|
||||
<ParamBoundingBoxHeight />
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -6,19 +6,14 @@ 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';
|
||||
import ParamScaledWidth from './ParamScaledWidth';
|
||||
|
||||
const ParamInfillCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const { isOpen, onToggle } = useDisclosure();
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.infillScalingHeader')}
|
||||
isOpen={isOpen}
|
||||
onToggle={onToggle}
|
||||
>
|
||||
<IAICollapse label={t('parameters.infillScalingHeader')}>
|
||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
||||
<ParamInfillMethod />
|
||||
<ParamInfillTilesize />
|
||||
|
@ -1,22 +1,16 @@
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
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}
|
||||
>
|
||||
<IAICollapse label={t('parameters.seamCorrectionHeader')}>
|
||||
<ParamSeamSize />
|
||||
<ParamSeamBlur />
|
||||
<ParamSeamStrength />
|
||||
|
@ -1,41 +1,45 @@
|
||||
import { Divider, Flex } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { Fragment, memo, useCallback } from 'react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import ControlNet from 'features/controlNet/components/ControlNet';
|
||||
import ParamControlNetFeatureToggle from 'features/controlNet/components/parameters/ParamControlNetFeatureToggle';
|
||||
import {
|
||||
controlNetAdded,
|
||||
controlNetSelector,
|
||||
isControlNetEnabledToggled,
|
||||
} from 'features/controlNet/store/controlNetSlice';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import { map } from 'lodash-es';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { getValidControlNets } from 'features/controlNet/util/getValidControlNets';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import ControlNet from 'features/controlNet/components/ControlNet';
|
||||
import { map } from 'lodash-es';
|
||||
import { Fragment, memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
const selector = createSelector(
|
||||
controlNetSelector,
|
||||
(controlNet) => {
|
||||
const { controlNets, isEnabled } = controlNet;
|
||||
|
||||
return { controlNetsArray: map(controlNets), isEnabled };
|
||||
const validControlNets = getValidControlNets(controlNets);
|
||||
|
||||
const activeLabel =
|
||||
isEnabled && validControlNets.length > 0
|
||||
? `${validControlNets.length} Active`
|
||||
: undefined;
|
||||
|
||||
return { controlNetsArray: map(controlNets), activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamControlNetCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const { controlNetsArray, isEnabled } = useAppSelector(selector);
|
||||
const { controlNetsArray, activeLabel } = useAppSelector(selector);
|
||||
const isControlNetDisabled = useFeatureStatus('controlNet').isFeatureDisabled;
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleClickControlNetToggle = useCallback(() => {
|
||||
dispatch(isControlNetEnabledToggled());
|
||||
}, [dispatch]);
|
||||
|
||||
const handleClickedAddControlNet = useCallback(() => {
|
||||
dispatch(controlNetAdded({ controlNetId: uuidv4() }));
|
||||
}, [dispatch]);
|
||||
@ -45,13 +49,9 @@ const ParamControlNetCollapse = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
label={'ControlNet'}
|
||||
isOpen={isEnabled}
|
||||
onToggle={handleClickControlNetToggle}
|
||||
withSwitch
|
||||
>
|
||||
<IAICollapse label="ControlNet" activeLabel={activeLabel}>
|
||||
<Flex sx={{ flexDir: 'column', gap: 3 }}>
|
||||
<ParamControlNetFeatureToggle />
|
||||
{controlNetsArray.map((c, i) => (
|
||||
<Fragment key={c.controlNetId}>
|
||||
{i > 0 && <Divider />}
|
||||
|
@ -1,37 +1,39 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { memo } from 'react';
|
||||
import { ParamHiresStrength } from './ParamHiresStrength';
|
||||
import { setHiresFix } from 'features/parameters/store/postprocessingSlice';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ParamHiresStrength } from './ParamHiresStrength';
|
||||
import { ParamHiresToggle } from './ParamHiresToggle';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const activeLabel = state.postprocessing.hiresFix ? 'Enabled' : undefined;
|
||||
|
||||
return { activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamHiresCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const hiresFix = useAppSelector(
|
||||
(state: RootState) => state.postprocessing.hiresFix
|
||||
);
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
const isHiresEnabled = useFeatureStatus('hires').isFeatureEnabled;
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleToggle = () => dispatch(setHiresFix(!hiresFix));
|
||||
|
||||
if (!isHiresEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.hiresOptim')}
|
||||
isOpen={hiresFix}
|
||||
onToggle={handleToggle}
|
||||
withSwitch
|
||||
>
|
||||
<IAICollapse label={t('parameters.hiresOptim')} activeLabel={activeLabel}>
|
||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
||||
<ParamHiresToggle />
|
||||
<ParamHiresStrength />
|
||||
</Flex>
|
||||
</IAICollapse>
|
||||
|
@ -23,7 +23,6 @@ export const ParamHiresToggle = () => {
|
||||
return (
|
||||
<IAISwitch
|
||||
label={t('parameters.hiresOptim')}
|
||||
fontSize="md"
|
||||
isChecked={hiresFix}
|
||||
onChange={handleChangeHiresFix}
|
||||
/>
|
||||
|
@ -1,27 +1,33 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import ParamPerlinNoise from './ParamPerlinNoise';
|
||||
import ParamNoiseThreshold from './ParamNoiseThreshold';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { setShouldUseNoiseSettings } from 'features/parameters/store/generationSlice';
|
||||
import { memo } from 'react';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ParamNoiseThreshold from './ParamNoiseThreshold';
|
||||
import { ParamNoiseToggle } from './ParamNoiseToggle';
|
||||
import ParamPerlinNoise from './ParamPerlinNoise';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { shouldUseNoiseSettings } = state.generation;
|
||||
return {
|
||||
activeLabel: shouldUseNoiseSettings ? 'Enabled' : undefined,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamNoiseCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const isNoiseEnabled = useFeatureStatus('noise').isFeatureEnabled;
|
||||
|
||||
const shouldUseNoiseSettings = useAppSelector(
|
||||
(state: RootState) => state.generation.shouldUseNoiseSettings
|
||||
);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleToggle = () =>
|
||||
dispatch(setShouldUseNoiseSettings(!shouldUseNoiseSettings));
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
if (!isNoiseEnabled) {
|
||||
return null;
|
||||
@ -30,11 +36,10 @@ const ParamNoiseCollapse = () => {
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.noiseSettings')}
|
||||
isOpen={shouldUseNoiseSettings}
|
||||
onToggle={handleToggle}
|
||||
withSwitch
|
||||
activeLabel={activeLabel}
|
||||
>
|
||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
||||
<ParamNoiseToggle />
|
||||
<ParamPerlinNoise />
|
||||
<ParamNoiseThreshold />
|
||||
</Flex>
|
||||
|
@ -1,18 +1,31 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setThreshold } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { shouldUseNoiseSettings, threshold } = state.generation;
|
||||
return {
|
||||
isDisabled: !shouldUseNoiseSettings,
|
||||
threshold,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
export default function ParamNoiseThreshold() {
|
||||
const dispatch = useAppDispatch();
|
||||
const threshold = useAppSelector(
|
||||
(state: RootState) => state.generation.threshold
|
||||
);
|
||||
const { threshold, isDisabled } = useAppSelector(selector);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
isDisabled={isDisabled}
|
||||
label={t('parameters.noiseThreshold')}
|
||||
min={0}
|
||||
max={20}
|
||||
|
@ -0,0 +1,27 @@
|
||||
import type { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldUseNoiseSettings } from 'features/parameters/store/generationSlice';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ParamNoiseToggle = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const shouldUseNoiseSettings = useAppSelector(
|
||||
(state: RootState) => state.generation.shouldUseNoiseSettings
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch(setShouldUseNoiseSettings(e.target.checked));
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label="Enable Noise Settings"
|
||||
isChecked={shouldUseNoiseSettings}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
};
|
@ -1,16 +1,31 @@
|
||||
import { RootState } from 'app/store/store';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAISlider from 'common/components/IAISlider';
|
||||
import { setPerlin } from 'features/parameters/store/generationSlice';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const { shouldUseNoiseSettings, perlin } = state.generation;
|
||||
return {
|
||||
isDisabled: !shouldUseNoiseSettings,
|
||||
perlin,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
export default function ParamPerlinNoise() {
|
||||
const dispatch = useAppDispatch();
|
||||
const perlin = useAppSelector((state: RootState) => state.generation.perlin);
|
||||
const { perlin, isDisabled } = useAppSelector(selector);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<IAISlider
|
||||
isDisabled={isDisabled}
|
||||
label={t('parameters.perlinNoise')}
|
||||
min={0}
|
||||
max={1}
|
||||
|
@ -1,36 +1,46 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { setSeamless } from 'features/parameters/store/generationSlice';
|
||||
import { memo } from 'react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ParamSeamlessXAxis from './ParamSeamlessXAxis';
|
||||
import ParamSeamlessYAxis from './ParamSeamlessYAxis';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
|
||||
const getActiveLabel = (seamlessXAxis: boolean, seamlessYAxis: boolean) => {
|
||||
if (seamlessXAxis && seamlessYAxis) {
|
||||
return 'X & Y';
|
||||
}
|
||||
|
||||
if (seamlessXAxis) {
|
||||
return 'X';
|
||||
}
|
||||
|
||||
if (seamlessYAxis) {
|
||||
return 'Y';
|
||||
}
|
||||
};
|
||||
|
||||
const selector = createSelector(
|
||||
generationSelector,
|
||||
(generation) => {
|
||||
const { shouldUseSeamless, seamlessXAxis, seamlessYAxis } = generation;
|
||||
const { seamlessXAxis, seamlessYAxis } = generation;
|
||||
|
||||
return { shouldUseSeamless, seamlessXAxis, seamlessYAxis };
|
||||
const activeLabel = getActiveLabel(seamlessXAxis, seamlessYAxis);
|
||||
return { activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamSeamlessCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const { shouldUseSeamless } = useAppSelector(selector);
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
const isSeamlessEnabled = useFeatureStatus('seamless').isFeatureEnabled;
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleToggle = () => dispatch(setSeamless(!shouldUseSeamless));
|
||||
|
||||
if (!isSeamlessEnabled) {
|
||||
return null;
|
||||
}
|
||||
@ -38,9 +48,7 @@ const ParamSeamlessCollapse = () => {
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.seamlessTiling')}
|
||||
isOpen={shouldUseSeamless}
|
||||
onToggle={handleToggle}
|
||||
withSwitch
|
||||
activeLabel={activeLabel}
|
||||
>
|
||||
<Flex sx={{ gap: 5 }}>
|
||||
<Box flexGrow={1}>
|
||||
|
@ -1,39 +1,39 @@
|
||||
import { memo } from 'react';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import ParamSymmetryHorizontal from './ParamSymmetryHorizontal';
|
||||
import ParamSymmetryVertical from './ParamSymmetryVertical';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { setShouldUseSymmetry } from 'features/parameters/store/generationSlice';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ParamSymmetryToggle from './ParamSymmetryToggle';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => ({
|
||||
activeLabel: state.generation.shouldUseSymmetry ? 'Enabled' : undefined,
|
||||
}),
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamSymmetryCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const shouldUseSymmetry = useAppSelector(
|
||||
(state: RootState) => state.generation.shouldUseSymmetry
|
||||
);
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
const isSymmetryEnabled = useFeatureStatus('symmetry').isFeatureEnabled;
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleToggle = () => dispatch(setShouldUseSymmetry(!shouldUseSymmetry));
|
||||
|
||||
if (!isSymmetryEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.symmetry')}
|
||||
isOpen={shouldUseSymmetry}
|
||||
onToggle={handleToggle}
|
||||
withSwitch
|
||||
>
|
||||
<IAICollapse label={t('parameters.symmetry')} activeLabel={activeLabel}>
|
||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
||||
<ParamSymmetryToggle />
|
||||
<ParamSymmetryHorizontal />
|
||||
<ParamSymmetryVertical />
|
||||
</Flex>
|
||||
|
@ -12,6 +12,7 @@ export default function ParamSymmetryToggle() {
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label="Enable Symmetry"
|
||||
isChecked={shouldUseSymmetry}
|
||||
onChange={(e) => dispatch(setShouldUseSymmetry(e.target.checked))}
|
||||
/>
|
||||
|
@ -1,39 +1,42 @@
|
||||
import ParamVariationWeights from './ParamVariationWeights';
|
||||
import ParamVariationAmount from './ParamVariationAmount';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { RootState } from 'app/store/store';
|
||||
import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import { memo } from 'react';
|
||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||
import { memo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ParamVariationAmount from './ParamVariationAmount';
|
||||
import { ParamVariationToggle } from './ParamVariationToggle';
|
||||
import ParamVariationWeights from './ParamVariationWeights';
|
||||
|
||||
const selector = createSelector(
|
||||
stateSelector,
|
||||
(state) => {
|
||||
const activeLabel = state.generation.shouldGenerateVariations
|
||||
? 'Enabled'
|
||||
: undefined;
|
||||
|
||||
return { activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamVariationCollapse = () => {
|
||||
const { t } = useTranslation();
|
||||
const shouldGenerateVariations = useAppSelector(
|
||||
(state: RootState) => state.generation.shouldGenerateVariations
|
||||
);
|
||||
const { activeLabel } = useAppSelector(selector);
|
||||
|
||||
const isVariationEnabled = useFeatureStatus('variation').isFeatureEnabled;
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleToggle = () =>
|
||||
dispatch(setShouldGenerateVariations(!shouldGenerateVariations));
|
||||
|
||||
if (!isVariationEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<IAICollapse
|
||||
label={t('parameters.variations')}
|
||||
isOpen={shouldGenerateVariations}
|
||||
onToggle={handleToggle}
|
||||
withSwitch
|
||||
>
|
||||
<IAICollapse label={t('parameters.variations')} activeLabel={activeLabel}>
|
||||
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
|
||||
<ParamVariationToggle />
|
||||
<ParamVariationAmount />
|
||||
<ParamVariationWeights />
|
||||
</Flex>
|
||||
|
@ -0,0 +1,27 @@
|
||||
import type { RootState } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAISwitch from 'common/components/IAISwitch';
|
||||
import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice';
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ParamVariationToggle = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const shouldGenerateVariations = useAppSelector(
|
||||
(state: RootState) => state.generation.shouldGenerateVariations
|
||||
);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) =>
|
||||
dispatch(setShouldGenerateVariations(e.target.checked));
|
||||
|
||||
return (
|
||||
<IAISwitch
|
||||
label="Enable Variations"
|
||||
isChecked={shouldGenerateVariations}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
};
|
@ -49,7 +49,6 @@ export interface GenerationState {
|
||||
verticalSymmetrySteps: number;
|
||||
model: ModelParam;
|
||||
vae: VAEParam;
|
||||
shouldUseSeamless: boolean;
|
||||
seamlessXAxis: boolean;
|
||||
seamlessYAxis: boolean;
|
||||
}
|
||||
@ -84,9 +83,8 @@ export const initialGenerationState: GenerationState = {
|
||||
verticalSymmetrySteps: 0,
|
||||
model: '',
|
||||
vae: '',
|
||||
shouldUseSeamless: false,
|
||||
seamlessXAxis: true,
|
||||
seamlessYAxis: true,
|
||||
seamlessXAxis: false,
|
||||
seamlessYAxis: false,
|
||||
};
|
||||
|
||||
const initialState: GenerationState = initialGenerationState;
|
||||
@ -144,9 +142,6 @@ export const generationSlice = createSlice({
|
||||
setImg2imgStrength: (state, action: PayloadAction<number>) => {
|
||||
state.img2imgStrength = action.payload;
|
||||
},
|
||||
setSeamless: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldUseSeamless = action.payload;
|
||||
},
|
||||
setSeamlessXAxis: (state, action: PayloadAction<boolean>) => {
|
||||
state.seamlessXAxis = action.payload;
|
||||
},
|
||||
@ -268,7 +263,6 @@ export const {
|
||||
modelSelected,
|
||||
vaeSelected,
|
||||
setShouldUseNoiseSettings,
|
||||
setSeamless,
|
||||
setSeamlessXAxis,
|
||||
setSeamlessYAxis,
|
||||
} = generationSlice.actions;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
@ -21,19 +21,25 @@ const selector = createSelector(
|
||||
[uiSelector, generationSelector],
|
||||
(ui, generation) => {
|
||||
const { shouldUseSliders } = ui;
|
||||
const { shouldFitToWidthHeight } = generation;
|
||||
const { shouldFitToWidthHeight, shouldRandomizeSeed } = generation;
|
||||
|
||||
return { shouldUseSliders, shouldFitToWidthHeight };
|
||||
const activeLabel = !shouldRandomizeSeed ? 'Manual Seed' : undefined;
|
||||
|
||||
return { shouldUseSliders, shouldFitToWidthHeight, activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ImageToImageTabCoreParameters = () => {
|
||||
const { shouldUseSliders, shouldFitToWidthHeight } = useAppSelector(selector);
|
||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
||||
const { shouldUseSliders, shouldFitToWidthHeight, activeLabel } =
|
||||
useAppSelector(selector);
|
||||
|
||||
return (
|
||||
<IAICollapse label={'General'} isOpen={isOpen} onToggle={onToggle}>
|
||||
<IAICollapse
|
||||
label={'General'}
|
||||
activeLabel={activeLabel}
|
||||
defaultIsOpen={true}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Box, Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
@ -11,25 +12,30 @@ import ParamScheduler from 'features/parameters/components/Parameters/Core/Param
|
||||
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
|
||||
import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth';
|
||||
import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import { memo } from 'react';
|
||||
|
||||
const selector = createSelector(
|
||||
uiSelector,
|
||||
(ui) => {
|
||||
stateSelector,
|
||||
({ ui, generation }) => {
|
||||
const { shouldUseSliders } = ui;
|
||||
const { shouldRandomizeSeed } = generation;
|
||||
|
||||
return { shouldUseSliders };
|
||||
const activeLabel = !shouldRandomizeSeed ? 'Manual Seed' : undefined;
|
||||
|
||||
return { shouldUseSliders, activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const TextToImageTabCoreParameters = () => {
|
||||
const { shouldUseSliders } = useAppSelector(selector);
|
||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
||||
const { shouldUseSliders, activeLabel } = useAppSelector(selector);
|
||||
|
||||
return (
|
||||
<IAICollapse label={'General'} isOpen={isOpen} onToggle={onToggle}>
|
||||
<IAICollapse
|
||||
label={'General'}
|
||||
activeLabel={activeLabel}
|
||||
defaultIsOpen={true}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Box, Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
@ -12,25 +13,30 @@ import ParamScheduler from 'features/parameters/components/Parameters/Core/Param
|
||||
import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps';
|
||||
import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength';
|
||||
import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull';
|
||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||
import { memo } from 'react';
|
||||
|
||||
const selector = createSelector(
|
||||
uiSelector,
|
||||
(ui) => {
|
||||
stateSelector,
|
||||
({ ui, generation }) => {
|
||||
const { shouldUseSliders } = ui;
|
||||
const { shouldRandomizeSeed } = generation;
|
||||
|
||||
return { shouldUseSliders };
|
||||
const activeLabel = !shouldRandomizeSeed ? 'Manual Seed' : undefined;
|
||||
|
||||
return { shouldUseSliders, activeLabel };
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const UnifiedCanvasCoreParameters = () => {
|
||||
const { shouldUseSliders } = useAppSelector(selector);
|
||||
const { isOpen, onToggle } = useDisclosure({ defaultIsOpen: true });
|
||||
const { shouldUseSliders, activeLabel } = useAppSelector(selector);
|
||||
|
||||
return (
|
||||
<IAICollapse label={'General'} isOpen={isOpen} onToggle={onToggle}>
|
||||
<IAICollapse
|
||||
label={'General'}
|
||||
activeLabel={activeLabel}
|
||||
defaultIsOpen={true}
|
||||
>
|
||||
<Flex
|
||||
sx={{
|
||||
flexDirection: 'column',
|
||||
|
Loading…
Reference in New Issue
Block a user