mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
translations and lint fix
This commit is contained in:
parent
442fc02429
commit
4cc41e0188
@ -1691,6 +1691,27 @@
|
||||
"missingUpscaleModel": "Missing upscale model",
|
||||
"missingTileControlNetModel": "No valid tile ControlNet models installed"
|
||||
},
|
||||
"stylePresets": {
|
||||
"active": "Active",
|
||||
"choosePromptTemplate": "Choose Prompt Template",
|
||||
"createPromptTemplate": "Create Prompt Template",
|
||||
"defaultTemplates": "Default Templates",
|
||||
"deleteImage": "Delete Image",
|
||||
"deleteTemplate": "Delete Template",
|
||||
"deleteTemplate2": "Are you sure you want to delete this template? This cannot be undone.",
|
||||
"editTemplate": "Edit Template",
|
||||
"myTemplates": "My Templates",
|
||||
"name": "Name",
|
||||
"negativePrompt": "Negative Prompt",
|
||||
"noMatchingTemplates": "No matching templates",
|
||||
"placeholderDirections": "Use the { } button to specify where your manual prompt should be included in the template. If you do not provide one, the template will be appended to your prompt.",
|
||||
"positivePrompt": "Positive Prompt",
|
||||
"templateDeleted": "Prompt template deleted",
|
||||
"unableToDeleteTemplate": "Unable to delete prompt template",
|
||||
"updatePromptTemplate": "Update Prompt Template",
|
||||
"uploadImage": "Upload Image",
|
||||
"useForTemplate": "Use For Prompt Template"
|
||||
},
|
||||
"upsell": {
|
||||
"inviteTeammates": "Invite Teammates",
|
||||
"professional": "Professional",
|
||||
|
@ -72,7 +72,7 @@ const allReducers = {
|
||||
[api.reducerPath]: api.reducer,
|
||||
[upscaleSlice.name]: upscaleSlice.reducer,
|
||||
[stylePresetModalSlice.name]: stylePresetModalSlice.reducer,
|
||||
[stylePresetSlice.name]: stylePresetSlice.reducer
|
||||
[stylePresetSlice.name]: stylePresetSlice.reducer,
|
||||
};
|
||||
|
||||
const rootReducer = combineReducers(allReducers);
|
||||
|
@ -6,7 +6,6 @@ import { useCopyImageToClipboard } from 'common/hooks/useCopyImageToClipboard';
|
||||
import { useDownloadImage } from 'common/hooks/useDownloadImage';
|
||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||
import { imagesToChangeSelected, isModalOpenChanged } from 'features/changeBoardModal/store/slice';
|
||||
import { isModalOpenChanged as isStylePresetModalOpenChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { iiLayerAdded } from 'features/controlLayers/store/controlLayersSlice';
|
||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||
import { useImageActions } from 'features/gallery/hooks/useImageActions';
|
||||
@ -41,8 +40,6 @@ import {
|
||||
} from 'react-icons/pi';
|
||||
import { useStarImagesMutation, useUnstarImagesMutation } from 'services/api/endpoints/images';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
import { isMenuOpenChanged } from '../../../stylePresets/store/stylePresetSlice';
|
||||
import { createPresetFromImageChanged } from '../../../stylePresets/store/stylePresetModalSlice';
|
||||
|
||||
type SingleSelectionMenuItemsProps = {
|
||||
imageDTO: ImageDTO;
|
||||
@ -200,7 +197,7 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
||||
onClickCapture={createAsPreset}
|
||||
isDisabled={isLoadingMetadata || !hasPrompts}
|
||||
>
|
||||
Create Preset
|
||||
{t('stylePresets.useForTemplate')}
|
||||
</MenuItem>
|
||||
<MenuDivider />
|
||||
<MenuItem icon={<PiShareFatBold />} onClickCapture={handleSendToImageToImage} id="send-to-img2img">
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useImageUrlToBlob } from 'common/hooks/useImageUrlToBlob';
|
||||
import { handlers, parseAndRecallAllMetadata, parseAndRecallPrompts } from 'features/metadata/util/handlers';
|
||||
import { isModalOpenChanged, prefilledFormDataChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
||||
import { useImageUrlToBlob } from '../../../common/hooks/useImageUrlToBlob';
|
||||
import { prefilledFormDataChanged, isModalOpenChanged } from '../../stylePresets/store/stylePresetModalSlice';
|
||||
import { useGetImageDTOQuery } from '../../../services/api/endpoints/images';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
|
||||
export const useImageActions = (image_name?: string) => {
|
||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||
@ -15,8 +15,8 @@ export const useImageActions = (image_name?: string) => {
|
||||
const [hasSeed, setHasSeed] = useState(false);
|
||||
const [hasPrompts, setHasPrompts] = useState(false);
|
||||
const imageUrlToBlob = useImageUrlToBlob();
|
||||
const dispatch = useAppDispatch()
|
||||
const { data: imageDTO } = useGetImageDTOQuery(image_name ?? skipToken)
|
||||
const dispatch = useAppDispatch();
|
||||
const { data: imageDTO } = useGetImageDTOQuery(image_name ?? skipToken);
|
||||
|
||||
useEffect(() => {
|
||||
const parseMetadata = async () => {
|
||||
@ -70,15 +70,31 @@ export const useImageActions = (image_name?: string) => {
|
||||
|
||||
const createAsPreset = useCallback(async () => {
|
||||
if (image_name && metadata && imageDTO) {
|
||||
const positivePrompt = await handlers.positivePrompt.parse(metadata)
|
||||
const negativePrompt = await handlers.negativePrompt.parse(metadata)
|
||||
const imageBlob = await imageUrlToBlob(imageDTO.image_url, 100)
|
||||
const positivePrompt = await handlers.positivePrompt.parse(metadata);
|
||||
const negativePrompt = await handlers.negativePrompt.parse(metadata);
|
||||
const imageBlob = await imageUrlToBlob(imageDTO.image_url, 100);
|
||||
|
||||
dispatch(prefilledFormDataChanged({ name: "", positivePrompt, negativePrompt, image: imageBlob ? new File([imageBlob], "stylePreset.png", { type: 'image/png', }) : null }))
|
||||
dispatch(isModalOpenChanged(true))
|
||||
dispatch(
|
||||
prefilledFormDataChanged({
|
||||
name: '',
|
||||
positivePrompt,
|
||||
negativePrompt,
|
||||
image: imageBlob ? new File([imageBlob], 'stylePreset.png', { type: 'image/png' }) : null,
|
||||
})
|
||||
);
|
||||
dispatch(isModalOpenChanged(true));
|
||||
}
|
||||
}, [image_name, metadata, dispatch, imageDTO, imageUrlToBlob]);
|
||||
|
||||
}, [image_name, metadata, dispatch, imageDTO])
|
||||
|
||||
return { recallAll, remix, recallSeed, recallPrompts, hasMetadata, hasSeed, hasPrompts, isLoadingMetadata, createAsPreset };
|
||||
return {
|
||||
recallAll,
|
||||
remix,
|
||||
recallSeed,
|
||||
recallPrompts,
|
||||
hasMetadata,
|
||||
hasSeed,
|
||||
hasPrompts,
|
||||
isLoadingMetadata,
|
||||
createAsPreset,
|
||||
};
|
||||
};
|
||||
|
@ -98,7 +98,8 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
|
||||
let modelNode;
|
||||
|
||||
if (model.base === 'sdxl') {
|
||||
const { positivePrompt, negativePrompt, positiveStylePrompt, negativeStylePrompt } = getPresetModifiedPrompts(state);
|
||||
const { positivePrompt, negativePrompt, positiveStylePrompt, negativeStylePrompt } =
|
||||
getPresetModifiedPrompts(state);
|
||||
|
||||
posCondNode = g.addNode({
|
||||
type: 'sdxl_compel_prompt',
|
||||
|
@ -16,7 +16,11 @@ import {
|
||||
POSITIVE_CONDITIONING,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
||||
|
||||
|
@ -19,7 +19,11 @@ import {
|
||||
POSITIVE_CONDITIONING,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||
|
||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
|
@ -23,7 +23,11 @@ import {
|
||||
POSITIVE_CONDITIONING,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||
|
||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
|
@ -16,7 +16,11 @@ import {
|
||||
SDXL_REFINER_SEAMLESS,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
||||
|
||||
|
@ -19,7 +19,11 @@ import {
|
||||
SDXL_REFINER_SEAMLESS,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||
|
||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
|
@ -23,7 +23,11 @@ import {
|
||||
SDXL_REFINER_SEAMLESS,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||
|
||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
|
@ -14,7 +14,11 @@ import {
|
||||
SDXL_REFINER_SEAMLESS,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import { isNonRefinerMainModelConfig, type NonNullableGraph } from 'services/api/types';
|
||||
|
||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
|
@ -14,7 +14,11 @@ import {
|
||||
POSITIVE_CONDITIONING,
|
||||
SEAMLESS,
|
||||
} from 'features/nodes/util/graph/constants';
|
||||
import { getBoardField, getIsIntermediate, getPresetModifiedPrompts } from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import {
|
||||
getBoardField,
|
||||
getIsIntermediate,
|
||||
getPresetModifiedPrompts,
|
||||
} from 'features/nodes/util/graph/graphBuilderUtils';
|
||||
import { isNonRefinerMainModelConfig, type NonNullableGraph } from 'services/api/types';
|
||||
|
||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||
|
@ -105,10 +105,10 @@ export const buildGenerationTabGraph = async (state: RootState): Promise<GraphTy
|
||||
const vaeLoader =
|
||||
vae?.base === model.base
|
||||
? g.addNode({
|
||||
type: 'vae_loader',
|
||||
id: VAE_LOADER,
|
||||
vae_model: vae,
|
||||
})
|
||||
type: 'vae_loader',
|
||||
id: VAE_LOADER,
|
||||
vae_model: vae,
|
||||
})
|
||||
: null;
|
||||
|
||||
let imageOutput: Invocation<'l2i'> | Invocation<'img_nsfw'> | Invocation<'img_watermark'> = l2i;
|
||||
|
@ -93,10 +93,10 @@ export const buildGenerationTabSDXLGraph = async (state: RootState): Promise<Non
|
||||
const vaeLoader =
|
||||
vae?.base === model.base
|
||||
? g.addNode({
|
||||
type: 'vae_loader',
|
||||
id: VAE_LOADER,
|
||||
vae_model: vae,
|
||||
})
|
||||
type: 'vae_loader',
|
||||
id: VAE_LOADER,
|
||||
vae_model: vae,
|
||||
})
|
||||
: null;
|
||||
|
||||
let imageOutput: Invocation<'l2i'> | Invocation<'img_nsfw'> | Invocation<'img_watermark'> = l2i;
|
||||
|
@ -17,22 +17,29 @@ export const getBoardField = (state: RootState): BoardField | undefined => {
|
||||
/**
|
||||
* Gets the prompts, modified for the active style preset.
|
||||
*/
|
||||
export const getPresetModifiedPrompts = (state: RootState): { positivePrompt: string; negativePrompt: string, positiveStylePrompt?: string; negativeStylePrompt?: string } => {
|
||||
export const getPresetModifiedPrompts = (
|
||||
state: RootState
|
||||
): { positivePrompt: string; negativePrompt: string; positiveStylePrompt?: string; negativeStylePrompt?: string } => {
|
||||
const { positivePrompt, negativePrompt, positivePrompt2, negativePrompt2, shouldConcatPrompts } =
|
||||
state.controlLayers.present;
|
||||
const { activeStylePreset } = state.stylePreset
|
||||
const { activeStylePreset } = state.stylePreset;
|
||||
|
||||
if (activeStylePreset) {
|
||||
const presetModifiedPositivePrompt = buildPresetModifiedPrompt(activeStylePreset.preset_data.positive_prompt, positivePrompt)
|
||||
const presetModifiedPositivePrompt = buildPresetModifiedPrompt(
|
||||
activeStylePreset.preset_data.positive_prompt,
|
||||
positivePrompt
|
||||
);
|
||||
|
||||
const presetModifiedNegativePrompt = buildPresetModifiedPrompt(activeStylePreset.preset_data.negative_prompt, negativePrompt)
|
||||
const presetModifiedNegativePrompt = buildPresetModifiedPrompt(
|
||||
activeStylePreset.preset_data.negative_prompt,
|
||||
negativePrompt
|
||||
);
|
||||
|
||||
return {
|
||||
positivePrompt: presetModifiedPositivePrompt,
|
||||
negativePrompt: presetModifiedNegativePrompt,
|
||||
positiveStylePrompt: shouldConcatPrompts ? presetModifiedPositivePrompt : positivePrompt2,
|
||||
negativeStylePrompt: shouldConcatPrompts ? presetModifiedNegativePrompt : negativePrompt2,
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,12 @@ import { Box, Textarea } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { negativePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||
import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt';
|
||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||
import { usePrompt } from 'features/prompt/usePrompt';
|
||||
import { memo, useCallback, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ViewModePrompt } from '../Prompts/ViewModePrompt';
|
||||
|
||||
const DEFAULT_HEIGHT = 20;
|
||||
|
||||
@ -42,7 +42,7 @@ export const ParamNegativePrompt = memo(() => {
|
||||
|
||||
return (
|
||||
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
||||
<Box pos="relative">
|
||||
<Box pos="relative" w="full">
|
||||
<Textarea
|
||||
id="negativePrompt"
|
||||
name="negativePrompt"
|
||||
|
@ -3,6 +3,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
||||
import { ShowDynamicPromptsPreviewButton } from 'features/dynamicPrompts/components/ShowDynamicPromptsPreviewButton';
|
||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||
import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt';
|
||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||
import { usePrompt } from 'features/prompt/usePrompt';
|
||||
@ -11,7 +12,6 @@ import { memo, useCallback, useRef } from 'react';
|
||||
import type { HotkeyCallback } from 'react-hotkeys-hook';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ViewModePrompt } from '../Prompts/ViewModePrompt';
|
||||
|
||||
const DEFAULT_HEIGHT = 28;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Flex, Icon, Text, Tooltip, Box } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from '../../../../app/store/storeHooks';
|
||||
import { Box, Flex, Icon, Text, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { viewModeChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { getViewModeChunks } from 'features/stylePresets/util/getViewModeChunks';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { PiEyeBold, PiQuestionBold } from 'react-icons/pi';
|
||||
import { viewModeChanged } from '../../../stylePresets/store/stylePresetSlice';
|
||||
import { getViewModeChunks } from '../../../stylePresets/util/getViewModeChunks';
|
||||
import { PiEyeBold } from 'react-icons/pi';
|
||||
|
||||
export const ViewModePrompt = ({
|
||||
presetPrompt,
|
||||
@ -51,11 +51,7 @@ export const ViewModePrompt = ({
|
||||
|
||||
<Box position="absolute" top={0} right={0} backgroundColor="rgba(0,0,0,0.75)" padding="2px 5px">
|
||||
<Flex alignItems="center" gap="1">
|
||||
<Tooltip
|
||||
label={
|
||||
'This is how your prompt will look with your currently selected preset. To edit your prompt, click anywhere in the text box.'
|
||||
}
|
||||
>
|
||||
<Tooltip label="This is how your prompt will look with your currently selected preset. To edit your prompt, click anywhere in the text box.">
|
||||
<Flex>
|
||||
<Icon as={PiEyeBold} color="base.500" boxSize="12px" />
|
||||
</Flex>
|
||||
|
@ -1,98 +0,0 @@
|
||||
import { useDisclosure } from '@invoke-ai/ui-library';
|
||||
import { isNil } from 'lodash-es';
|
||||
import type { ChangeEventHandler, FormEvent, FormEventHandler, KeyboardEventHandler, RefObject, SyntheticEvent } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
|
||||
type UseInsertTriggerArg = {
|
||||
prompt: string;
|
||||
paragraphRef: RefObject<HTMLParagraphElement>;
|
||||
onChange: (v: string) => void;
|
||||
};
|
||||
|
||||
export const usePromptContentEditable = ({ prompt, paragraphRef, onChange: _onChange }: UseInsertTriggerArg) => {
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
|
||||
|
||||
const onChange = useCallback(
|
||||
(e: any) => {
|
||||
e.preventDefault();
|
||||
_onChange(e.data)
|
||||
},
|
||||
[_onChange]
|
||||
);
|
||||
|
||||
|
||||
const insertTrigger = useCallback(
|
||||
(v: string) => {
|
||||
const element = paragraphRef.current;
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = window.getSelection();
|
||||
if (!selection || selection.rangeCount === 0) {
|
||||
// Insert at the end if no selection found
|
||||
const newPrompt = prompt + v;
|
||||
flushSync(() => {
|
||||
_onChange(newPrompt);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
const cursorPosition = range.startOffset;
|
||||
|
||||
|
||||
console.log({ cursorPosition })
|
||||
|
||||
|
||||
const updatedPrompt = prompt.slice(0, cursorPosition) + v + prompt.slice(cursorPosition);
|
||||
|
||||
console.log({ updatedPrompt })
|
||||
|
||||
flushSync(() => {
|
||||
_onChange(updatedPrompt);
|
||||
});
|
||||
|
||||
},
|
||||
[paragraphRef, _onChange, prompt]
|
||||
);
|
||||
|
||||
const onFocus = useCallback(() => {
|
||||
paragraphRef.current?.focus();
|
||||
}, [paragraphRef]);
|
||||
|
||||
const handleClosePopover = useCallback(() => {
|
||||
onClose();
|
||||
onFocus();
|
||||
}, [onFocus, onClose]);
|
||||
|
||||
const onSelect = useCallback(
|
||||
(v: string) => {
|
||||
insertTrigger(v)
|
||||
handleClosePopover();
|
||||
},
|
||||
[handleClosePopover, insertTrigger]
|
||||
);
|
||||
|
||||
const onKeyDown: KeyboardEventHandler<HTMLParagraphElement> = useCallback(
|
||||
(e) => {
|
||||
if (e.key === '<') {
|
||||
onOpen();
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
[onOpen]
|
||||
);
|
||||
|
||||
return {
|
||||
onChange,
|
||||
isOpen,
|
||||
onClose,
|
||||
onOpen,
|
||||
onSelect,
|
||||
onKeyDown,
|
||||
onFocus,
|
||||
};
|
||||
};
|
@ -1,17 +1,20 @@
|
||||
import { Flex, IconButton, Text, Box, ButtonGroup } from '@invoke-ai/ui-library';
|
||||
import { Flex, IconButton, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { negativePromptChanged, positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
||||
import { usePresetModifiedPrompts } from 'features/stylePresets/hooks/usePresetModifiedPrompts';
|
||||
import { activeStylePresetChanged, viewModeChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import type { MouseEventHandler } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiEyeBold, PiStackSimpleBold, PiXBold } from 'react-icons/pi';
|
||||
|
||||
import StylePresetImage from './StylePresetImage';
|
||||
|
||||
export const ActiveStylePreset = () => {
|
||||
const { activeStylePreset, viewMode } = useAppSelector((s) => s.stylePreset);
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { presetModifiedPositivePrompt, presetModifiedNegativePrompt } = usePresetModifiedPrompts();
|
||||
|
||||
@ -47,7 +50,7 @@ export const ActiveStylePreset = () => {
|
||||
return (
|
||||
<Flex h="25px" alignItems="center">
|
||||
<Text fontSize="sm" fontWeight="semibold" color="base.300">
|
||||
Choose Preset
|
||||
{t('stylePresets.choosePromptTemplate')}
|
||||
</Text>
|
||||
</Flex>
|
||||
);
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Button, Flex, FormControl, FormLabel, Icon, Input, Text } from '@invoke-ai/ui-library';
|
||||
import { Button, Flex, FormControl, FormLabel, Input, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { isModalOpenChanged, updatingStylePresetIdChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { useCallback } from 'react';
|
||||
import type { SubmitHandler } from 'react-hook-form';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { PiBracketsCurlyBold } from 'react-icons/pi';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCreateStylePresetMutation, useUpdateStylePresetMutation } from 'services/api/endpoints/stylePresets';
|
||||
|
||||
import { StylePresetPromptField } from './StylePresetPromptField';
|
||||
import { StylePresetImageField } from './StylePresetImageField';
|
||||
import { StylePresetPromptField } from './StylePresetPromptField';
|
||||
|
||||
export type StylePresetFormData = {
|
||||
name: string;
|
||||
@ -22,10 +22,11 @@ export const StylePresetForm = ({ updatingStylePresetId }: { updatingStylePreset
|
||||
const [createStylePreset] = useCreateStylePresetMutation();
|
||||
const [updateStylePreset] = useUpdateStylePresetMutation();
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const defaultValues = useAppSelector((s) => s.stylePresetModal.prefilledFormData);
|
||||
|
||||
const { handleSubmit, control, formState, reset, register } = useForm<StylePresetFormData>({
|
||||
const { handleSubmit, control, register } = useForm<StylePresetFormData>({
|
||||
defaultValues: defaultValues || {
|
||||
name: '',
|
||||
positivePrompt: '',
|
||||
@ -70,19 +71,18 @@ export const StylePresetForm = ({ updatingStylePresetId }: { updatingStylePreset
|
||||
<Flex alignItems="center" gap="4">
|
||||
<StylePresetImageField control={control} name="image" />
|
||||
<FormControl orientation="vertical">
|
||||
<FormLabel>Name</FormLabel>
|
||||
<FormLabel>{t('stylePresets.name')}</FormLabel>
|
||||
<Input size="md" {...register('name')} />
|
||||
</FormControl>
|
||||
</Flex>
|
||||
|
||||
<StylePresetPromptField label="Positive Prompt" control={control} name="positivePrompt" />
|
||||
<StylePresetPromptField label="Negative Prompt" control={control} name="negativePrompt" />
|
||||
<Text variant="subtext">
|
||||
Use the <Icon as={PiBracketsCurlyBold} /> button to specify where your manual prompt should be included in the
|
||||
template. If you do not provide one, the template will be appended to your prompt.
|
||||
</Text>
|
||||
<Text variant="subtext">{t('stylePresets.placeholderDirections')}</Text>
|
||||
|
||||
<Button onClick={handleSubmit(handleClickSave)}>Save</Button>
|
||||
<Flex justifyContent="flex-end">
|
||||
<Button onClick={handleSubmit(handleClickSave)}>{t('common.save')}</Button>
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { Tooltip, Flex, Button, Icon, Box, Image, IconButton } from '@invoke-ai/ui-library';
|
||||
import { t } from 'i18next';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { Box, Button, Flex, Icon, IconButton, Image, Tooltip } from '@invoke-ai/ui-library';
|
||||
import { useCallback } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
import { useController } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiArrowCounterClockwiseBold, PiUploadSimpleBold } from 'react-icons/pi';
|
||||
import { useController, UseControllerProps } from 'react-hook-form';
|
||||
import { StylePresetFormData } from './StylePresetForm';
|
||||
|
||||
import type { StylePresetFormData } from './StylePresetForm';
|
||||
|
||||
export const StylePresetImageField = (props: UseControllerProps<StylePresetFormData>) => {
|
||||
const { field } = useController(props);
|
||||
const { t } = useTranslation();
|
||||
const onDropAccepted = useCallback(
|
||||
(files: File[]) => {
|
||||
const file = files[0];
|
||||
@ -15,12 +18,12 @@ export const StylePresetImageField = (props: UseControllerProps<StylePresetFormD
|
||||
field.onChange(file);
|
||||
}
|
||||
},
|
||||
[field, t]
|
||||
[field]
|
||||
);
|
||||
|
||||
const handleResetImage = useCallback(() => {
|
||||
field.onChange(null);
|
||||
}, []);
|
||||
}, [field]);
|
||||
|
||||
const { getInputProps, getRootProps } = useDropzone({
|
||||
accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] },
|
||||
@ -46,8 +49,8 @@ export const StylePresetImageField = (props: UseControllerProps<StylePresetFormD
|
||||
insetInlineEnd={0}
|
||||
insetBlockStart={0}
|
||||
onClick={handleResetImage}
|
||||
aria-label={t('modelManager.deleteModelImage')}
|
||||
tooltip={t('modelManager.deleteModelImage')}
|
||||
aria-label={t('stylePresets.deleteImage')}
|
||||
tooltip={t('stylePresets.deleteImage')}
|
||||
icon={<PiArrowCounterClockwiseBold />}
|
||||
size="md"
|
||||
variant="ghost"
|
||||
@ -58,7 +61,7 @@ export const StylePresetImageField = (props: UseControllerProps<StylePresetFormD
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip label={t('modelManager.uploadImage')}>
|
||||
<Tooltip label={t('stylePresets.uploadImage')}>
|
||||
<Flex
|
||||
as={Button}
|
||||
w={65}
|
||||
|
@ -1,18 +1,21 @@
|
||||
import { Badge, ConfirmationAlertDialog, Flex, IconButton, Text, useDisclosure } from '@invoke-ai/ui-library';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useImageUrlToBlob } from 'common/hooks/useImageUrlToBlob';
|
||||
import {
|
||||
isModalOpenChanged,
|
||||
prefilledFormDataChanged,
|
||||
updatingStylePresetIdChanged,
|
||||
} from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { activeStylePresetChanged, isMenuOpenChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiPencilBold, PiTrashBold } from 'react-icons/pi';
|
||||
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||
import { useDeleteStylePresetMutation } from 'services/api/endpoints/stylePresets';
|
||||
|
||||
import StylePresetImage from './StylePresetImage';
|
||||
import { useImageUrlToBlob } from 'common/hooks/useImageUrlToBlob';
|
||||
|
||||
export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithImage }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
@ -20,6 +23,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
const activeStylePreset = useAppSelector((s) => s.stylePreset.activeStylePreset);
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const imageUrlToBlob = useImageUrlToBlob();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleClickEdit = useCallback(
|
||||
async (e: MouseEvent<HTMLButtonElement>) => {
|
||||
@ -43,7 +47,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
dispatch(updatingStylePresetIdChanged(preset.id));
|
||||
dispatch(isModalOpenChanged(true));
|
||||
},
|
||||
[dispatch, preset]
|
||||
[dispatch, preset, imageUrlToBlob]
|
||||
);
|
||||
|
||||
const handleClickApply = useCallback(async () => {
|
||||
@ -56,14 +60,23 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
e.stopPropagation();
|
||||
onOpen();
|
||||
},
|
||||
[dispatch, preset]
|
||||
[onOpen]
|
||||
);
|
||||
|
||||
const handleDeletePreset = useCallback(async () => {
|
||||
try {
|
||||
await deleteStylePreset(preset.id);
|
||||
} catch (error) {}
|
||||
}, [preset]);
|
||||
toast({
|
||||
status: 'success',
|
||||
title: t('stylePresets.templateDeleted'),
|
||||
});
|
||||
} catch (error) {
|
||||
toast({
|
||||
status: 'error',
|
||||
title: t('stylePresets.unableToDeleteTemplate'),
|
||||
});
|
||||
}
|
||||
}, [preset, t, deleteStylePreset]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -92,7 +105,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
bg="transparent"
|
||||
flexShrink={0}
|
||||
>
|
||||
Active
|
||||
{t('stylePresets.active')}
|
||||
</Badge>
|
||||
)}
|
||||
</Flex>
|
||||
@ -101,14 +114,14 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label="Edit"
|
||||
aria-label={t('stylePresets.editTemplate')}
|
||||
onClick={handleClickEdit}
|
||||
icon={<PiPencilBold />}
|
||||
/>
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label="Delete"
|
||||
aria-label={t('stylePresets.deleteTemplate')}
|
||||
onClick={handleClickDelete}
|
||||
colorScheme="error"
|
||||
icon={<PiTrashBold />}
|
||||
@ -116,16 +129,16 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<Flex flexDir="column">
|
||||
<Flex flexDir="column" gap="1">
|
||||
<Text fontSize="xs">
|
||||
<Text as="span" fontWeight="semibold">
|
||||
Positive prompt:
|
||||
{t('stylePresets.positivePrompt')}:
|
||||
</Text>{' '}
|
||||
{preset.preset_data.positive_prompt}
|
||||
</Text>
|
||||
<Text fontSize="xs">
|
||||
<Text as="span" fontWeight="semibold">
|
||||
Negative prompt:
|
||||
{t('stylePresets.negativePrompt')}:
|
||||
</Text>{' '}
|
||||
{preset.preset_data.negative_prompt}
|
||||
</Text>
|
||||
@ -135,12 +148,11 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
<ConfirmationAlertDialog
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
title={'Delete preset'}
|
||||
title={t('stylePresets.deleteTemplate')}
|
||||
acceptCallback={handleDeletePreset}
|
||||
acceptButtonText={'Delete'}
|
||||
acceptButtonText="Delete"
|
||||
>
|
||||
<p>{'Delete Preset?'}</p>
|
||||
<br />
|
||||
<p>{t('stylePresets.deleteTemplate2')}</p>
|
||||
</ConfirmationAlertDialog>
|
||||
</>
|
||||
);
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
updatingStylePresetIdChanged,
|
||||
} from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiPlusBold } from 'react-icons/pi';
|
||||
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||
import { useListStylePresetsQuery } from 'services/api/endpoints/stylePresets';
|
||||
@ -42,6 +43,7 @@ export const StylePresetMenu = () => {
|
||||
});
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleClickAddNew = useCallback(() => {
|
||||
dispatch(prefilledFormDataChanged(null));
|
||||
@ -67,13 +69,13 @@ export const StylePresetMenu = () => {
|
||||
|
||||
{data.presets.length === 0 && data.defaultPresets.length === 0 && (
|
||||
<Text m="20px" textAlign="center">
|
||||
No matching presets
|
||||
{t('stylePrests.noMatchingTemplates')}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<StylePresetList title="My Presets" data={data.presets} />
|
||||
<StylePresetList title={t('stylePresets.myTemplates')} data={data.presets} />
|
||||
|
||||
<StylePresetList title="Default Presets" data={data.defaultPresets} />
|
||||
<StylePresetList title={t('stylePresets.defaultTemplates')} data={data.defaultPresets} />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@ -10,17 +10,19 @@ import {
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { isModalOpenChanged, updatingStylePresetIdChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { StylePresetForm } from './StylePresetForm';
|
||||
|
||||
export const StylePresetModal = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
const isModalOpen = useAppSelector((s) => s.stylePresetModal.isModalOpen);
|
||||
const updatingStylePresetId = useAppSelector((s) => s.stylePresetModal.updatingStylePresetId);
|
||||
|
||||
const modalTitle = useMemo(() => {
|
||||
return updatingStylePresetId ? `Update Style Preset` : `Create Style Preset`;
|
||||
}, [updatingStylePresetId]);
|
||||
return updatingStylePresetId ? t('stylePresets.updatePromptTemplate') : t('stylePresets.createPromptTemplate');
|
||||
}, [updatingStylePresetId, t]);
|
||||
|
||||
const handleCloseModal = useCallback(() => {
|
||||
dispatch(updatingStylePresetIdChanged(null));
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Flex, FormControl, FormLabel, IconButton, Textarea } from '@invoke-ai/ui-library';
|
||||
import { PRESET_PLACEHOLDER } from 'features/stylePresets/hooks/usePresetModifiedPrompts';
|
||||
import type { ChangeEventHandler } from 'react';
|
||||
import { useCallback, useMemo, useRef } from 'react';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
@ -6,7 +7,6 @@ import { useController } from 'react-hook-form';
|
||||
import { PiBracketsCurlyBold } from 'react-icons/pi';
|
||||
|
||||
import type { StylePresetFormData } from './StylePresetForm';
|
||||
import { PRESET_PLACEHOLDER } from '../hooks/usePresetModifiedPrompts';
|
||||
|
||||
interface Props extends UseControllerProps<StylePresetFormData> {
|
||||
label: string;
|
||||
|
@ -1,25 +1,27 @@
|
||||
import { useAppSelector } from "app/store/storeHooks"
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
|
||||
export const PRESET_PLACEHOLDER = `{prompt}`
|
||||
export const PRESET_PLACEHOLDER = `{prompt}`;
|
||||
|
||||
export const buildPresetModifiedPrompt = (presetPrompt: string, currentPrompt: string) => {
|
||||
return presetPrompt.includes(PRESET_PLACEHOLDER) ? presetPrompt.replace(new RegExp(PRESET_PLACEHOLDER), currentPrompt) : `${currentPrompt} ${presetPrompt}`
|
||||
}
|
||||
|
||||
return presetPrompt.includes(PRESET_PLACEHOLDER)
|
||||
? presetPrompt.replace(new RegExp(PRESET_PLACEHOLDER), currentPrompt)
|
||||
: `${currentPrompt} ${presetPrompt}`;
|
||||
};
|
||||
|
||||
export const usePresetModifiedPrompts = () => {
|
||||
const activeStylePreset = useAppSelector(s => s.stylePreset.activeStylePreset)
|
||||
const { positivePrompt, negativePrompt } = useAppSelector(s => s.controlLayers.present)
|
||||
const activeStylePreset = useAppSelector((s) => s.stylePreset.activeStylePreset);
|
||||
const { positivePrompt, negativePrompt } = useAppSelector((s) => s.controlLayers.present);
|
||||
|
||||
if (!activeStylePreset) {
|
||||
return { presetModifiedPositivePrompt: positivePrompt, presetModifiedNegativePrompt: negativePrompt }
|
||||
}
|
||||
if (!activeStylePreset) {
|
||||
return { presetModifiedPositivePrompt: positivePrompt, presetModifiedNegativePrompt: negativePrompt };
|
||||
}
|
||||
|
||||
const { positive_prompt: presetPositivePrompt, negative_prompt: presetNegativePrompt } = activeStylePreset.preset_data;
|
||||
const { positive_prompt: presetPositivePrompt, negative_prompt: presetNegativePrompt } =
|
||||
activeStylePreset.preset_data;
|
||||
|
||||
const presetModifiedPositivePrompt = buildPresetModifiedPrompt(presetPositivePrompt, positivePrompt)
|
||||
const presetModifiedPositivePrompt = buildPresetModifiedPrompt(presetPositivePrompt, positivePrompt);
|
||||
|
||||
const presetModifiedNegativePrompt = buildPresetModifiedPrompt(presetNegativePrompt, negativePrompt)
|
||||
const presetModifiedNegativePrompt = buildPresetModifiedPrompt(presetNegativePrompt, negativePrompt);
|
||||
|
||||
return { presetModifiedPositivePrompt, presetModifiedNegativePrompt }
|
||||
}
|
||||
return { presetModifiedPositivePrompt, presetModifiedNegativePrompt };
|
||||
};
|
||||
|
@ -1,34 +1,33 @@
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { RootState } from 'app/store/store';
|
||||
import type { StylePresetFormData } from 'features/stylePresets/components/StylePresetForm';
|
||||
|
||||
import type { StylePresetModalState } from './types';
|
||||
import { StylePresetFormData } from '../components/StylePresetForm';
|
||||
|
||||
|
||||
export const initialState: StylePresetModalState = {
|
||||
isModalOpen: false,
|
||||
updatingStylePresetId: null,
|
||||
prefilledFormData: null
|
||||
isModalOpen: false,
|
||||
updatingStylePresetId: null,
|
||||
prefilledFormData: null,
|
||||
};
|
||||
|
||||
|
||||
export const stylePresetModalSlice = createSlice({
|
||||
name: 'stylePresetModal',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
isModalOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isModalOpen = action.payload;
|
||||
},
|
||||
updatingStylePresetIdChanged: (state, action: PayloadAction<string | null>) => {
|
||||
state.updatingStylePresetId = action.payload;
|
||||
},
|
||||
prefilledFormDataChanged: (state, action: PayloadAction<StylePresetFormData | null>) => {
|
||||
state.prefilledFormData = action.payload;
|
||||
},
|
||||
name: 'stylePresetModal',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
isModalOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isModalOpen = action.payload;
|
||||
},
|
||||
updatingStylePresetIdChanged: (state, action: PayloadAction<string | null>) => {
|
||||
state.updatingStylePresetId = action.payload;
|
||||
},
|
||||
prefilledFormDataChanged: (state, action: PayloadAction<StylePresetFormData | null>) => {
|
||||
state.prefilledFormData = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { isModalOpenChanged, updatingStylePresetIdChanged, prefilledFormDataChanged } = stylePresetModalSlice.actions;
|
||||
export const { isModalOpenChanged, updatingStylePresetIdChanged, prefilledFormDataChanged } =
|
||||
stylePresetModalSlice.actions;
|
||||
|
||||
export const selectStylePresetModalSlice = (state: RootState) => state.stylePresetModal;
|
||||
|
@ -5,34 +5,33 @@ import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePre
|
||||
|
||||
import type { StylePresetState } from './types';
|
||||
|
||||
|
||||
export const initialState: StylePresetState = {
|
||||
isMenuOpen: false,
|
||||
activeStylePreset: null,
|
||||
searchTerm: "",
|
||||
viewMode: false
|
||||
isMenuOpen: false,
|
||||
activeStylePreset: null,
|
||||
searchTerm: '',
|
||||
viewMode: false,
|
||||
};
|
||||
|
||||
|
||||
export const stylePresetSlice = createSlice({
|
||||
name: 'stylePreset',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
isMenuOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isMenuOpen = action.payload;
|
||||
},
|
||||
activeStylePresetChanged: (state, action: PayloadAction<StylePresetRecordWithImage | null>) => {
|
||||
state.activeStylePreset = action.payload;
|
||||
},
|
||||
searchTermChanged: (state, action: PayloadAction<string>) => {
|
||||
state.searchTerm = action.payload;
|
||||
},
|
||||
viewModeChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.viewMode = action.payload;
|
||||
},
|
||||
name: 'stylePreset',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
isMenuOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isMenuOpen = action.payload;
|
||||
},
|
||||
activeStylePresetChanged: (state, action: PayloadAction<StylePresetRecordWithImage | null>) => {
|
||||
state.activeStylePreset = action.payload;
|
||||
},
|
||||
searchTermChanged: (state, action: PayloadAction<string>) => {
|
||||
state.searchTerm = action.payload;
|
||||
},
|
||||
viewModeChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.viewMode = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { isMenuOpenChanged, activeStylePresetChanged, searchTermChanged, viewModeChanged } = stylePresetSlice.actions;
|
||||
export const { isMenuOpenChanged, activeStylePresetChanged, searchTermChanged, viewModeChanged } =
|
||||
stylePresetSlice.actions;
|
||||
|
||||
export const selectStylePresetSlice = (state: RootState) => state.stylePreset;
|
||||
|
@ -1,17 +1,15 @@
|
||||
import type { StylePresetRecordWithImage } from "services/api/endpoints/stylePresets";
|
||||
import { StylePresetFormData } from "../components/StylePresetForm";
|
||||
import type { StylePresetFormData } from 'features/stylePresets/components/StylePresetForm';
|
||||
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||
|
||||
export type StylePresetModalState = {
|
||||
isModalOpen: boolean;
|
||||
updatingStylePresetId: string | null;
|
||||
prefilledFormData: StylePresetFormData | null
|
||||
isModalOpen: boolean;
|
||||
updatingStylePresetId: string | null;
|
||||
prefilledFormData: StylePresetFormData | null;
|
||||
};
|
||||
|
||||
|
||||
export type StylePresetState = {
|
||||
isMenuOpen: boolean;
|
||||
activeStylePreset: StylePresetRecordWithImage | null;
|
||||
searchTerm: string;
|
||||
viewMode: boolean;
|
||||
}
|
||||
|
||||
isMenuOpen: boolean;
|
||||
activeStylePreset: StylePresetRecordWithImage | null;
|
||||
searchTerm: string;
|
||||
viewMode: boolean;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PRESET_PLACEHOLDER } from '../hooks/usePresetModifiedPrompts';
|
||||
import { PRESET_PLACEHOLDER } from 'features/stylePresets/hooks/usePresetModifiedPrompts';
|
||||
|
||||
export const getViewModeChunks = (currentPrompt: string, presetPrompt?: string) => {
|
||||
if (!presetPrompt || !presetPrompt.length) {
|
||||
|
@ -9,11 +9,11 @@ import { ControlSettingsAccordion } from 'features/settingsAccordions/components
|
||||
import { GenerationSettingsAccordion } from 'features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion';
|
||||
import { ImageSettingsAccordion } from 'features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion';
|
||||
import { RefinerSettingsAccordion } from 'features/settingsAccordions/components/RefinerSettingsAccordion/RefinerSettingsAccordion';
|
||||
import { StylePresetMenu } from 'features/stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from 'features/stylePresets/components/StylePresetMenuTrigger';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo } from 'react';
|
||||
import { StylePresetMenu } from '../../../stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from '../../../stylePresets/components/StylePresetMenuTrigger';
|
||||
|
||||
const overlayScrollbarsStyles: CSSProperties = {
|
||||
height: '100%',
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
||||
import QueueControls from 'features/queue/components/QueueControls';
|
||||
import { AdvancedSettingsAccordion } from 'features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion';
|
||||
import { GenerationSettingsAccordion } from 'features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion';
|
||||
import { UpscaleSettingsAccordion } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion';
|
||||
import { StylePresetMenu } from 'features/stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from 'features/stylePresets/components/StylePresetMenuTrigger';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo } from 'react';
|
||||
import { useAppSelector } from '../../../../app/store/storeHooks';
|
||||
import { StylePresetMenu } from '../../../stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from '../../../stylePresets/components/StylePresetMenuTrigger';
|
||||
|
||||
const overlayScrollbarsStyles: CSSProperties = {
|
||||
height: '100%',
|
||||
|
@ -2,7 +2,8 @@ import type { paths } from 'services/api/schema';
|
||||
|
||||
import { api, buildV1Url, LIST_TAG } from '..';
|
||||
|
||||
export type StylePresetRecordWithImage = paths['/api/v1/style_presets/i/{style_preset_id}']['get']['responses']['200']['content']['application/json']
|
||||
export type StylePresetRecordWithImage =
|
||||
paths['/api/v1/style_presets/i/{style_preset_id}']['get']['responses']['200']['content']['application/json'];
|
||||
|
||||
/**
|
||||
* Builds an endpoint URL for the style_presets router
|
||||
@ -60,7 +61,9 @@ export const stylePresetsApi = api.injectEndpoints({
|
||||
}),
|
||||
updateStylePreset: build.mutation<
|
||||
paths['/api/v1/style_presets/i/{style_preset_id}']['patch']['responses']['200']['content']['application/json'],
|
||||
paths['/api/v1/style_presets/i/{style_preset_id}']['patch']['requestBody']['content']['multipart/form-data'] & { id: string }
|
||||
paths['/api/v1/style_presets/i/{style_preset_id}']['patch']['requestBody']['content']['multipart/form-data'] & {
|
||||
id: string;
|
||||
}
|
||||
>({
|
||||
query: ({ id, name, positive_prompt, negative_prompt, image }) => {
|
||||
const formData = new FormData();
|
||||
@ -72,12 +75,11 @@ export const stylePresetsApi = api.injectEndpoints({
|
||||
formData.append('positive_prompt', positive_prompt);
|
||||
formData.append('negative_prompt', negative_prompt);
|
||||
|
||||
|
||||
return {
|
||||
url: buildStylePresetsUrl(`i/${id}`),
|
||||
method: 'PATCH',
|
||||
body: formData
|
||||
}
|
||||
body: formData,
|
||||
};
|
||||
},
|
||||
invalidatesTags: (response, error, { id }) => [
|
||||
{ type: 'StylePreset', id: LIST_TAG },
|
||||
|
Loading…
Reference in New Issue
Block a user