mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
fixed merge conflicts
This commit is contained in:
@@ -6,6 +6,7 @@ import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAICollapse from 'common/components/IAICollapse';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import ControlNet from 'features/controlNet/components/ControlNet';
|
||||
import IPAdapterPanel from 'features/controlNet/components/ipAdapter/IPAdapterPanel';
|
||||
import ParamControlNetFeatureToggle from 'features/controlNet/components/parameters/ParamControlNetFeatureToggle';
|
||||
import {
|
||||
controlNetAdded,
|
||||
@@ -25,14 +26,23 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
const selector = createSelector(
|
||||
[stateSelector],
|
||||
({ controlNet }) => {
|
||||
const { controlNets, isEnabled } = controlNet;
|
||||
const { controlNets, isEnabled, isIPAdapterEnabled } = controlNet;
|
||||
|
||||
const validControlNets = getValidControlNets(controlNets);
|
||||
|
||||
const activeLabel =
|
||||
isEnabled && validControlNets.length > 0
|
||||
? `${validControlNets.length} Active`
|
||||
: undefined;
|
||||
let activeLabel = undefined;
|
||||
|
||||
if (isEnabled && validControlNets.length > 0) {
|
||||
activeLabel = `${validControlNets.length} ControlNet`;
|
||||
}
|
||||
|
||||
if (isIPAdapterEnabled) {
|
||||
if (activeLabel) {
|
||||
activeLabel = `${activeLabel}, IP Adapter`;
|
||||
} else {
|
||||
activeLabel = 'IP Adapter';
|
||||
}
|
||||
}
|
||||
|
||||
return { controlNetsArray: map(controlNets), activeLabel };
|
||||
},
|
||||
@@ -101,6 +111,7 @@ const ParamControlNetCollapse = () => {
|
||||
<ControlNet controlNet={c} />
|
||||
</Fragment>
|
||||
))}
|
||||
<IPAdapterPanel />
|
||||
</Flex>
|
||||
</IAICollapse>
|
||||
);
|
||||
|
||||
@@ -16,8 +16,6 @@ const selector = createSelector(
|
||||
state.config.sd.iterations;
|
||||
const { iterations } = state.generation;
|
||||
const { shouldUseSliders } = state.ui;
|
||||
const isDisabled =
|
||||
state.dynamicPrompts.isEnabled && state.dynamicPrompts.combinatorial;
|
||||
|
||||
const step = state.hotkeys.shift ? fineStep : coarseStep;
|
||||
|
||||
@@ -29,13 +27,16 @@ const selector = createSelector(
|
||||
inputMax,
|
||||
step,
|
||||
shouldUseSliders,
|
||||
isDisabled,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
const ParamIterations = () => {
|
||||
type Props = {
|
||||
asSlider?: boolean;
|
||||
};
|
||||
|
||||
const ParamIterations = ({ asSlider }: Props) => {
|
||||
const {
|
||||
iterations,
|
||||
initial,
|
||||
@@ -44,7 +45,6 @@ const ParamIterations = () => {
|
||||
inputMax,
|
||||
step,
|
||||
shouldUseSliders,
|
||||
isDisabled,
|
||||
} = useAppSelector(selector);
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
@@ -60,11 +60,10 @@ const ParamIterations = () => {
|
||||
dispatch(setIterations(initial));
|
||||
}, [dispatch, initial]);
|
||||
|
||||
return shouldUseSliders ? (
|
||||
return asSlider || shouldUseSliders ? (
|
||||
<IAIInformationalPopover details="paramImages">
|
||||
<IAISlider
|
||||
isDisabled={isDisabled}
|
||||
label={t('parameters.images')}
|
||||
label={t('parameters.iterations')}
|
||||
step={step}
|
||||
min={min}
|
||||
max={sliderMax}
|
||||
@@ -80,8 +79,7 @@ const ParamIterations = () => {
|
||||
) : (
|
||||
<IAIInformationalPopover details="paramImages">
|
||||
<IAINumberInput
|
||||
isDisabled={isDisabled}
|
||||
label={t('parameters.images')}
|
||||
label={t('parameters.iterations')}
|
||||
step={step}
|
||||
min={min}
|
||||
max={inputMax}
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import { Box, FormControl, useDisclosure } from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
|
||||
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import {
|
||||
clampSymmetrySteps,
|
||||
setPositivePrompt,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
|
||||
import { userInvoked } from 'app/store/actions';
|
||||
import IAITextarea from 'common/components/IAITextarea';
|
||||
import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke';
|
||||
import AddEmbeddingButton from 'features/embedding/components/AddEmbeddingButton';
|
||||
import ParamEmbeddingPopover from 'features/embedding/components/ParamEmbeddingPopover';
|
||||
import { setPositivePrompt } from 'features/parameters/store/generationSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { ChangeEvent, KeyboardEvent, memo, useCallback, useRef } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -23,11 +15,10 @@ import { useFeatureStatus } from '../../../../system/hooks/useFeatureStatus';
|
||||
import IAIInformationalPopover from '../../../../../common/components/IAIInformationalPopover';
|
||||
|
||||
const promptInputSelector = createSelector(
|
||||
[stateSelector, activeTabNameSelector],
|
||||
({ generation }, activeTabName) => {
|
||||
[stateSelector],
|
||||
({ generation }) => {
|
||||
return {
|
||||
prompt: generation.positivePrompt,
|
||||
activeTabName,
|
||||
};
|
||||
},
|
||||
{
|
||||
@@ -42,8 +33,7 @@ const promptInputSelector = createSelector(
|
||||
*/
|
||||
const ParamPositiveConditioning = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { prompt, activeTabName } = useAppSelector(promptInputSelector);
|
||||
const isReady = useIsReadyToInvoke();
|
||||
const { prompt } = useAppSelector(promptInputSelector);
|
||||
const promptRef = useRef<HTMLTextAreaElement>(null);
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
const { t } = useTranslation();
|
||||
@@ -105,23 +95,13 @@ const ParamPositiveConditioning = () => {
|
||||
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
if (e.key === 'Enter' && e.shiftKey === false && isReady) {
|
||||
e.preventDefault();
|
||||
dispatch(clampSymmetrySteps());
|
||||
dispatch(userInvoked(activeTabName));
|
||||
}
|
||||
if (isEmbeddingEnabled && e.key === '<') {
|
||||
onOpen();
|
||||
}
|
||||
},
|
||||
[isReady, dispatch, activeTabName, onOpen, isEmbeddingEnabled]
|
||||
[onOpen, isEmbeddingEnabled]
|
||||
);
|
||||
|
||||
// const handleSelect = (e: MouseEvent<HTMLTextAreaElement>) => {
|
||||
// const target = e.target as HTMLTextAreaElement;
|
||||
// setCaret({ start: target.selectionStart, end: target.selectionEnd });
|
||||
// };
|
||||
|
||||
return (
|
||||
<Box position="relative">
|
||||
<FormControl>
|
||||
|
||||
@@ -17,6 +17,7 @@ import ParamAspectRatio, { mappedAspectRatios } from './ParamAspectRatio';
|
||||
import ParamHeight from './ParamHeight';
|
||||
import ParamWidth from './ParamWidth';
|
||||
import IAIInformationalPopover from 'common/components/IAIInformationalPopover';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
|
||||
const sizeOptsSelector = createSelector(
|
||||
[generationSelector, activeTabNameSelector],
|
||||
@@ -31,7 +32,8 @@ const sizeOptsSelector = createSelector(
|
||||
width,
|
||||
height,
|
||||
};
|
||||
}
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
export default function ParamSize() {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { upscaleRequested } from 'app/store/middleware/listenerMiddleware/listeners/upscaleRequested';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import IAIPopover from 'common/components/IAIPopover';
|
||||
import { selectIsBusy } from 'features/system/store/systemSelectors';
|
||||
import { useIsQueueMutationInProgress } from 'features/queue/hooks/useIsQueueMutationInProgress';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaExpandArrowsAlt } from 'react-icons/fa';
|
||||
import { FaExpand } from 'react-icons/fa';
|
||||
import { ImageDTO } from 'services/api/types';
|
||||
import ParamESRGANModel from './ParamRealESRGANModel';
|
||||
|
||||
@@ -16,7 +16,7 @@ type Props = { imageDTO?: ImageDTO };
|
||||
const ParamUpscalePopover = (props: Props) => {
|
||||
const { imageDTO } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
const isBusy = useAppSelector(selectIsBusy);
|
||||
const inProgress = useIsQueueMutationInProgress();
|
||||
const { t } = useTranslation();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
|
||||
@@ -34,8 +34,9 @@ const ParamUpscalePopover = (props: Props) => {
|
||||
onClose={onClose}
|
||||
triggerComponent={
|
||||
<IAIIconButton
|
||||
tooltip={t('parameters.upscale')}
|
||||
onClick={onOpen}
|
||||
icon={<FaExpandArrowsAlt />}
|
||||
icon={<FaExpand />}
|
||||
aria-label={t('parameters.upscale')}
|
||||
/>
|
||||
}
|
||||
@@ -49,7 +50,7 @@ const ParamUpscalePopover = (props: Props) => {
|
||||
<ParamESRGANModel />
|
||||
<IAIButton
|
||||
size="sm"
|
||||
isDisabled={!imageDTO || isBusy}
|
||||
isDisabled={!imageDTO || inProgress}
|
||||
onClick={handleClickUpscale}
|
||||
>
|
||||
{t('parameters.upscaleImage')}
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
import {
|
||||
ButtonGroup,
|
||||
ButtonProps,
|
||||
ButtonSpinner,
|
||||
Menu,
|
||||
MenuButton,
|
||||
MenuItemOption,
|
||||
MenuList,
|
||||
MenuOptionGroup,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import IAIIconButton from 'common/components/IAIIconButton';
|
||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||
import {
|
||||
CancelStrategy,
|
||||
SystemState,
|
||||
cancelScheduled,
|
||||
cancelTypeChanged,
|
||||
} from 'features/system/store/systemSlice';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MdCancel, MdCancelScheduleSend } from 'react-icons/md';
|
||||
|
||||
import { ChevronDownIcon } from '@chakra-ui/icons';
|
||||
import { sessionCanceled } from 'services/api/thunks/session';
|
||||
import IAIButton from 'common/components/IAIButton';
|
||||
|
||||
const cancelButtonSelector = createSelector(
|
||||
systemSelector,
|
||||
(system: SystemState) => {
|
||||
return {
|
||||
isProcessing: system.isProcessing,
|
||||
isConnected: system.isConnected,
|
||||
isCancelable: system.isCancelable,
|
||||
currentIteration: system.currentIteration,
|
||||
totalIterations: system.totalIterations,
|
||||
sessionId: system.sessionId,
|
||||
cancelType: system.cancelType,
|
||||
isCancelScheduled: system.isCancelScheduled,
|
||||
};
|
||||
},
|
||||
{
|
||||
memoizeOptions: {
|
||||
resultEqualityCheck: isEqual,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
type Props = Omit<ButtonProps, 'aria-label'> & {
|
||||
btnGroupWidth?: string | number;
|
||||
asIconButton?: boolean;
|
||||
};
|
||||
|
||||
const CancelButton = (props: Props) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { btnGroupWidth = 'auto', asIconButton = false, ...rest } = props;
|
||||
const {
|
||||
isProcessing,
|
||||
isConnected,
|
||||
isCancelable,
|
||||
cancelType,
|
||||
isCancelScheduled,
|
||||
sessionId,
|
||||
} = useAppSelector(cancelButtonSelector);
|
||||
|
||||
const handleClickCancel = useCallback(() => {
|
||||
if (!sessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cancelType === 'scheduled') {
|
||||
dispatch(cancelScheduled());
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(sessionCanceled({ session_id: sessionId }));
|
||||
}, [dispatch, sessionId, cancelType]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleCancelTypeChanged = useCallback(
|
||||
(value: string | string[]) => {
|
||||
const newCancelType = Array.isArray(value) ? value[0] : value;
|
||||
dispatch(cancelTypeChanged(newCancelType as CancelStrategy));
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
useHotkeys(
|
||||
'shift+x',
|
||||
() => {
|
||||
if ((isConnected || isProcessing) && isCancelable) {
|
||||
handleClickCancel();
|
||||
}
|
||||
},
|
||||
[isConnected, isProcessing, isCancelable]
|
||||
);
|
||||
|
||||
const cancelLabel = useMemo(() => {
|
||||
if (isCancelScheduled) {
|
||||
return t('parameters.cancel.isScheduled');
|
||||
}
|
||||
if (cancelType === 'immediate') {
|
||||
return t('parameters.cancel.immediate');
|
||||
}
|
||||
|
||||
return t('parameters.cancel.schedule');
|
||||
}, [t, cancelType, isCancelScheduled]);
|
||||
|
||||
const cancelIcon = useMemo(() => {
|
||||
if (isCancelScheduled) {
|
||||
return <ButtonSpinner />;
|
||||
}
|
||||
if (cancelType === 'immediate') {
|
||||
return <MdCancel />;
|
||||
}
|
||||
|
||||
return <MdCancelScheduleSend />;
|
||||
}, [cancelType, isCancelScheduled]);
|
||||
|
||||
return (
|
||||
<ButtonGroup isAttached width={btnGroupWidth}>
|
||||
{asIconButton ? (
|
||||
<IAIIconButton
|
||||
icon={cancelIcon}
|
||||
tooltip={cancelLabel}
|
||||
aria-label={cancelLabel}
|
||||
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
||||
onClick={handleClickCancel}
|
||||
colorScheme="error"
|
||||
id="cancel-button"
|
||||
{...rest}
|
||||
/>
|
||||
) : (
|
||||
<IAIButton
|
||||
leftIcon={cancelIcon}
|
||||
tooltip={cancelLabel}
|
||||
aria-label={cancelLabel}
|
||||
isDisabled={!isConnected || !isProcessing || !isCancelable}
|
||||
onClick={handleClickCancel}
|
||||
colorScheme="error"
|
||||
id="cancel-button"
|
||||
{...rest}
|
||||
>
|
||||
{t('parameters.cancel.cancel')}
|
||||
</IAIButton>
|
||||
)}
|
||||
<Menu closeOnSelect={false}>
|
||||
<MenuButton
|
||||
as={IAIIconButton}
|
||||
tooltip={t('parameters.cancel.setType')}
|
||||
aria-label={t('parameters.cancel.setType')}
|
||||
icon={<ChevronDownIcon w="1em" h="1em" />}
|
||||
paddingX={0}
|
||||
paddingY={0}
|
||||
colorScheme="error"
|
||||
minWidth={5}
|
||||
{...rest}
|
||||
/>
|
||||
<MenuList minWidth="240px">
|
||||
<MenuOptionGroup
|
||||
value={cancelType}
|
||||
title="Cancel Type"
|
||||
type="radio"
|
||||
onChange={handleCancelTypeChanged}
|
||||
>
|
||||
<MenuItemOption value="immediate">
|
||||
{t('parameters.cancel.immediate')}
|
||||
</MenuItemOption>
|
||||
<MenuItemOption value="scheduled">
|
||||
{t('parameters.cancel.schedule')}
|
||||
</MenuItemOption>
|
||||
</MenuOptionGroup>
|
||||
</MenuList>
|
||||
</Menu>
|
||||
</ButtonGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(CancelButton);
|
||||
@@ -1,174 +0,0 @@
|
||||
import {
|
||||
Box,
|
||||
Divider,
|
||||
Flex,
|
||||
ListItem,
|
||||
Text,
|
||||
UnorderedList,
|
||||
} from '@chakra-ui/react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { userInvoked } from 'app/store/actions';
|
||||
import { stateSelector } from 'app/store/store';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||
import IAIButton, { IAIButtonProps } from 'common/components/IAIButton';
|
||||
import IAIIconButton, {
|
||||
IAIIconButtonProps,
|
||||
} from 'common/components/IAIIconButton';
|
||||
import { useIsReadyToInvoke } from 'common/hooks/useIsReadyToInvoke';
|
||||
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
|
||||
import ProgressBar from 'features/system/components/ProgressBar';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FaPlay } from 'react-icons/fa';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
|
||||
interface InvokeButton
|
||||
extends Omit<IAIButtonProps | IAIIconButtonProps, 'aria-label'> {
|
||||
asIconButton?: boolean;
|
||||
}
|
||||
|
||||
export default function InvokeButton(props: InvokeButton) {
|
||||
const { asIconButton = false, sx, ...rest } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
const { isReady, isProcessing } = useIsReadyToInvoke();
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
|
||||
const handleInvoke = useCallback(() => {
|
||||
dispatch(clampSymmetrySteps());
|
||||
dispatch(userInvoked(activeTabName));
|
||||
}, [dispatch, activeTabName]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useHotkeys(
|
||||
['ctrl+enter', 'meta+enter'],
|
||||
handleInvoke,
|
||||
{
|
||||
enabled: () => isReady,
|
||||
preventDefault: true,
|
||||
enableOnFormTags: ['input', 'textarea', 'select'],
|
||||
},
|
||||
[isReady, activeTabName]
|
||||
);
|
||||
|
||||
return (
|
||||
<Box style={{ flexGrow: 4 }} position="relative">
|
||||
<Box style={{ position: 'relative' }}>
|
||||
{!isReady && (
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
bottom: '0',
|
||||
left: '0',
|
||||
right: '0',
|
||||
height: '100%',
|
||||
overflow: 'clip',
|
||||
borderRadius: 'base',
|
||||
...sx,
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
<ProgressBar />
|
||||
</Box>
|
||||
)}
|
||||
{asIconButton ? (
|
||||
<IAIIconButton
|
||||
aria-label={t('parameters.invoke.invoke')}
|
||||
type="submit"
|
||||
icon={<FaPlay />}
|
||||
isDisabled={!isReady}
|
||||
onClick={handleInvoke}
|
||||
tooltip={<InvokeButtonTooltipContent />}
|
||||
colorScheme="accent"
|
||||
isLoading={isProcessing}
|
||||
id="invoke-button"
|
||||
data-progress={isProcessing}
|
||||
sx={{
|
||||
w: 'full',
|
||||
flexGrow: 1,
|
||||
...sx,
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
) : (
|
||||
<IAIButton
|
||||
tooltip={<InvokeButtonTooltipContent />}
|
||||
aria-label={t('parameters.invoke.invoke')}
|
||||
type="submit"
|
||||
data-progress={isProcessing}
|
||||
isDisabled={!isReady}
|
||||
onClick={handleInvoke}
|
||||
colorScheme="accent"
|
||||
id="invoke-button"
|
||||
leftIcon={isProcessing ? undefined : <FaPlay />}
|
||||
isLoading={isProcessing}
|
||||
loadingText={t('parameters.invoke.invoke')}
|
||||
sx={{
|
||||
w: 'full',
|
||||
flexGrow: 1,
|
||||
fontWeight: 700,
|
||||
...sx,
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
Invoke
|
||||
</IAIButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const tooltipSelector = createSelector(
|
||||
[stateSelector],
|
||||
({ gallery }) => {
|
||||
const { autoAddBoardId } = gallery;
|
||||
|
||||
return {
|
||||
autoAddBoardId,
|
||||
};
|
||||
},
|
||||
defaultSelectorOptions
|
||||
);
|
||||
|
||||
export const InvokeButtonTooltipContent = memo(() => {
|
||||
const { isReady, reasons } = useIsReadyToInvoke();
|
||||
const { autoAddBoardId } = useAppSelector(tooltipSelector);
|
||||
const autoAddBoardName = useBoardName(autoAddBoardId);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Flex flexDir="column" gap={1}>
|
||||
<Text fontWeight={600}>
|
||||
{isReady
|
||||
? t('parameters.invoke.readyToInvoke')
|
||||
: t('parameters.invoke.unableToInvoke')}
|
||||
</Text>
|
||||
{reasons.length > 0 && (
|
||||
<UnorderedList>
|
||||
{reasons.map((reason, i) => (
|
||||
<ListItem key={`${reason}.${i}`}>
|
||||
<Text fontWeight={400}>{reason}</Text>
|
||||
</ListItem>
|
||||
))}
|
||||
</UnorderedList>
|
||||
)}
|
||||
<Divider
|
||||
opacity={0.2}
|
||||
borderColor="base.50"
|
||||
_dark={{ borderColor: 'base.900' }}
|
||||
/>
|
||||
<Text fontWeight={400} fontStyle="oblique 10deg">
|
||||
{t('parameters.invoke.addingImagesTo')}{' '}
|
||||
<Text as="span" fontWeight={600}>
|
||||
{autoAddBoardName || 'Uncategorized'}
|
||||
</Text>
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
});
|
||||
|
||||
InvokeButtonTooltipContent.displayName = 'InvokeButtonTooltipContent';
|
||||
@@ -1,18 +0,0 @@
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { memo } from 'react';
|
||||
import CancelButton from './CancelButton';
|
||||
import InvokeButton from './InvokeButton';
|
||||
|
||||
/**
|
||||
* Buttons to start and cancel image generation.
|
||||
*/
|
||||
const ProcessButtons = () => {
|
||||
return (
|
||||
<Flex layerStyle="first" sx={{ gap: 2, borderRadius: 'base', p: 2 }}>
|
||||
<InvokeButton />
|
||||
<CancelButton />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(ProcessButtons);
|
||||
@@ -1,6 +1,7 @@
|
||||
import { components } from 'services/api/schema';
|
||||
|
||||
export const MODEL_TYPE_MAP = {
|
||||
any: 'Any',
|
||||
'sd-1': 'Stable Diffusion 1.x',
|
||||
'sd-2': 'Stable Diffusion 2.x',
|
||||
sdxl: 'Stable Diffusion XL',
|
||||
@@ -8,6 +9,7 @@ export const MODEL_TYPE_MAP = {
|
||||
};
|
||||
|
||||
export const MODEL_TYPE_SHORT_MAP = {
|
||||
any: 'Any',
|
||||
'sd-1': 'SD1',
|
||||
'sd-2': 'SD2',
|
||||
sdxl: 'SDXL',
|
||||
@@ -15,6 +17,10 @@ export const MODEL_TYPE_SHORT_MAP = {
|
||||
};
|
||||
|
||||
export const clipSkipMap = {
|
||||
any: {
|
||||
maxClip: 0,
|
||||
markers: [],
|
||||
},
|
||||
'sd-1': {
|
||||
maxClip: 12,
|
||||
markers: [0, 1, 2, 3, 4, 8, 12],
|
||||
|
||||
@@ -210,7 +210,13 @@ export type HeightParam = z.infer<typeof zHeight>;
|
||||
export const isValidHeight = (val: unknown): val is HeightParam =>
|
||||
zHeight.safeParse(val).success;
|
||||
|
||||
export const zBaseModel = z.enum(['sd-1', 'sd-2', 'sdxl', 'sdxl-refiner']);
|
||||
export const zBaseModel = z.enum([
|
||||
'any',
|
||||
'sd-1',
|
||||
'sd-2',
|
||||
'sdxl',
|
||||
'sdxl-refiner',
|
||||
]);
|
||||
|
||||
export type BaseModelParam = z.infer<typeof zBaseModel>;
|
||||
|
||||
@@ -323,7 +329,17 @@ export type ControlNetModelParam = z.infer<typeof zLoRAModel>;
|
||||
export const isValidControlNetModel = (
|
||||
val: unknown
|
||||
): val is ControlNetModelParam => zControlNetModel.safeParse(val).success;
|
||||
|
||||
/**
|
||||
* Zod schema for IP-Adapter models
|
||||
*/
|
||||
export const zIPAdapterModel = z.object({
|
||||
model_name: z.string().min(1),
|
||||
base_model: zBaseModel,
|
||||
});
|
||||
/**
|
||||
* Type alias for model parameter, inferred from its zod schema
|
||||
*/
|
||||
export type IPAdapterModelParam = z.infer<typeof zIPAdapterModel>;
|
||||
/**
|
||||
* Zod schema for l2l strength parameter
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { logger } from 'app/logging/logger';
|
||||
import { zIPAdapterModel } from 'features/parameters/types/parameterSchemas';
|
||||
import { IPAdapterModelField } from 'services/api/types';
|
||||
|
||||
export const modelIdToIPAdapterModelParam = (
|
||||
ipAdapterModelId: string
|
||||
): IPAdapterModelField | undefined => {
|
||||
const log = logger('models');
|
||||
const [base_model, _model_type, model_name] = ipAdapterModelId.split('/');
|
||||
|
||||
const result = zIPAdapterModel.safeParse({
|
||||
base_model,
|
||||
model_name,
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
log.error(
|
||||
{
|
||||
ipAdapterModelId,
|
||||
errors: result.error.format(),
|
||||
},
|
||||
'Failed to parse IP-Adapter model id'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return result.data;
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const useCoreParametersCollapseLabel = () => {
|
||||
const { t } = useTranslation();
|
||||
const shouldRandomizeSeed = useAppSelector(
|
||||
(state) => state.generation.shouldRandomizeSeed
|
||||
);
|
||||
const iterations = useAppSelector((state) => state.generation.iterations);
|
||||
|
||||
const iterationsLabel = useMemo(() => {
|
||||
if (iterations === 1) {
|
||||
return t('parameters.iterationsWithCount_one', { count: 1 });
|
||||
} else {
|
||||
return t('parameters.iterationsWithCount_other', { count: iterations });
|
||||
}
|
||||
}, [iterations, t]);
|
||||
|
||||
const seedLabel = useMemo(() => {
|
||||
if (shouldRandomizeSeed) {
|
||||
return t('parameters.randomSeed');
|
||||
} else {
|
||||
return t('parameters.manualSeed');
|
||||
}
|
||||
}, [shouldRandomizeSeed, t]);
|
||||
|
||||
const iterationsAndSeedLabel = useMemo(
|
||||
() => [iterationsLabel, seedLabel].join(', '),
|
||||
[iterationsLabel, seedLabel]
|
||||
);
|
||||
|
||||
return { iterationsAndSeedLabel, iterationsLabel, seedLabel };
|
||||
};
|
||||
Reference in New Issue
Block a user