mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
ui: add ability to copy template
This commit is contained in:
parent
4837e578b2
commit
096f001634
@ -1693,6 +1693,7 @@
|
||||
"active": "Active",
|
||||
"choosePromptTemplate": "Choose Prompt Template",
|
||||
"clearTemplateSelection": "Clear Template Selection",
|
||||
"copyTemplate": "Copy Template",
|
||||
"createPromptTemplate": "Create Prompt Template",
|
||||
"defaultTemplates": "Default Templates",
|
||||
"deleteImage": "Delete Image",
|
||||
|
@ -43,9 +43,6 @@ export const ParamNegativePrompt = memo(() => {
|
||||
return (
|
||||
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
||||
<Box pos="relative" w="full">
|
||||
{viewMode && (
|
||||
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.negative_prompt || ''} />
|
||||
)}
|
||||
<Textarea
|
||||
id="negativePrompt"
|
||||
name="negativePrompt"
|
||||
@ -61,6 +58,9 @@ export const ParamNegativePrompt = memo(() => {
|
||||
<PromptOverlayButtonWrapper>
|
||||
<AddPromptTriggerButton isOpen={isOpen} onOpen={onOpen} />
|
||||
</PromptOverlayButtonWrapper>
|
||||
{viewMode && (
|
||||
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.negative_prompt || ''} />
|
||||
)}
|
||||
</Box>
|
||||
</PromptPopover>
|
||||
);
|
||||
|
@ -58,9 +58,6 @@ export const ParamPositivePrompt = memo(() => {
|
||||
return (
|
||||
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
||||
<Box pos="relative">
|
||||
{viewMode && (
|
||||
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.positive_prompt || ''} />
|
||||
)}
|
||||
<Textarea
|
||||
id="prompt"
|
||||
name="prompt"
|
||||
@ -78,6 +75,9 @@ export const ParamPositivePrompt = memo(() => {
|
||||
{baseModel === 'sdxl' && <SDXLConcatButton />}
|
||||
<ShowDynamicPromptsPreviewButton />
|
||||
</PromptOverlayButtonWrapper>
|
||||
{viewMode && (
|
||||
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.positive_prompt || ''} />
|
||||
)}
|
||||
</Box>
|
||||
</PromptPopover>
|
||||
);
|
||||
|
@ -19,7 +19,7 @@ export const ViewModePrompt = ({ presetPrompt, prompt }: { presetPrompt: string;
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<Box position="absolute" top={0} bottom={0} left={0} right={0} zIndex={1} layerStyle="second" borderRadius="base">
|
||||
<Box position="absolute" top={0} bottom={0} left={0} right={0} layerStyle="second" borderRadius="base">
|
||||
<Flex flexDir="column" onClick={handleExitViewMode} justifyContent="space-between" h="full" padding="8px 10px">
|
||||
<Flex overflow="scroll">
|
||||
<Text fontSize="sm" lineHeight="1rem" w="full">
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { Button, Flex, FormControl, FormLabel, Input, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { isModalOpenChanged, updatingStylePresetIdChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import {
|
||||
isModalOpenChanged,
|
||||
prefilledFormDataChanged,
|
||||
updatingStylePresetIdChanged,
|
||||
} from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import { useCallback } from 'react';
|
||||
import type { SubmitHandler } from 'react-hook-form';
|
||||
@ -65,6 +69,7 @@ export const StylePresetForm = ({
|
||||
});
|
||||
}
|
||||
|
||||
dispatch(prefilledFormDataChanged(null));
|
||||
dispatch(updatingStylePresetIdChanged(null));
|
||||
dispatch(isModalOpenChanged(false));
|
||||
},
|
||||
|
@ -11,7 +11,7 @@ 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 { PiCopyBold, PiPencilBold, PiTrashBold } from 'react-icons/pi';
|
||||
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||
import { useDeleteStylePresetMutation } from 'services/api/endpoints/stylePresets';
|
||||
|
||||
@ -58,6 +58,27 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
[onOpen]
|
||||
);
|
||||
|
||||
const handleClickCopy = useCallback(
|
||||
(e: MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation();
|
||||
const { name, preset_data } = preset;
|
||||
const { positive_prompt, negative_prompt } = preset_data;
|
||||
|
||||
dispatch(
|
||||
prefilledFormDataChanged({
|
||||
name: `${name} (${t('common.copy')})`,
|
||||
positivePrompt: positive_prompt || '',
|
||||
negativePrompt: negative_prompt || '',
|
||||
imageUrl: preset.image,
|
||||
})
|
||||
);
|
||||
|
||||
dispatch(updatingStylePresetIdChanged(null));
|
||||
dispatch(isModalOpenChanged(true));
|
||||
},
|
||||
[dispatch, preset, t]
|
||||
);
|
||||
|
||||
const handleDeletePreset = useCallback(async () => {
|
||||
try {
|
||||
await deleteStylePreset(preset.id);
|
||||
@ -106,8 +127,16 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
{preset.type !== 'default' && (
|
||||
<Flex alignItems="center" gap={1}>
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={t('stylePresets.copyTemplate')}
|
||||
onClick={handleClickCopy}
|
||||
icon={<PiCopyBold />}
|
||||
/>
|
||||
{preset.type !== 'default' && (
|
||||
<>
|
||||
<IconButton
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@ -123,9 +152,10 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
colorScheme="error"
|
||||
icon={<PiTrashBold />}
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<Flex flexDir="column" gap={1}>
|
||||
<Text fontSize="xs">
|
||||
|
Loading…
Reference in New Issue
Block a user