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",
|
"active": "Active",
|
||||||
"choosePromptTemplate": "Choose Prompt Template",
|
"choosePromptTemplate": "Choose Prompt Template",
|
||||||
"clearTemplateSelection": "Clear Template Selection",
|
"clearTemplateSelection": "Clear Template Selection",
|
||||||
|
"copyTemplate": "Copy Template",
|
||||||
"createPromptTemplate": "Create Prompt Template",
|
"createPromptTemplate": "Create Prompt Template",
|
||||||
"defaultTemplates": "Default Templates",
|
"defaultTemplates": "Default Templates",
|
||||||
"deleteImage": "Delete Image",
|
"deleteImage": "Delete Image",
|
||||||
|
@ -43,9 +43,6 @@ export const ParamNegativePrompt = memo(() => {
|
|||||||
return (
|
return (
|
||||||
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
||||||
<Box pos="relative" w="full">
|
<Box pos="relative" w="full">
|
||||||
{viewMode && (
|
|
||||||
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.negative_prompt || ''} />
|
|
||||||
)}
|
|
||||||
<Textarea
|
<Textarea
|
||||||
id="negativePrompt"
|
id="negativePrompt"
|
||||||
name="negativePrompt"
|
name="negativePrompt"
|
||||||
@ -61,6 +58,9 @@ export const ParamNegativePrompt = memo(() => {
|
|||||||
<PromptOverlayButtonWrapper>
|
<PromptOverlayButtonWrapper>
|
||||||
<AddPromptTriggerButton isOpen={isOpen} onOpen={onOpen} />
|
<AddPromptTriggerButton isOpen={isOpen} onOpen={onOpen} />
|
||||||
</PromptOverlayButtonWrapper>
|
</PromptOverlayButtonWrapper>
|
||||||
|
{viewMode && (
|
||||||
|
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.negative_prompt || ''} />
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</PromptPopover>
|
</PromptPopover>
|
||||||
);
|
);
|
||||||
|
@ -58,9 +58,6 @@ export const ParamPositivePrompt = memo(() => {
|
|||||||
return (
|
return (
|
||||||
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
<PromptPopover isOpen={isOpen} onClose={onClose} onSelect={onSelect} width={textareaRef.current?.clientWidth}>
|
||||||
<Box pos="relative">
|
<Box pos="relative">
|
||||||
{viewMode && (
|
|
||||||
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.positive_prompt || ''} />
|
|
||||||
)}
|
|
||||||
<Textarea
|
<Textarea
|
||||||
id="prompt"
|
id="prompt"
|
||||||
name="prompt"
|
name="prompt"
|
||||||
@ -78,6 +75,9 @@ export const ParamPositivePrompt = memo(() => {
|
|||||||
{baseModel === 'sdxl' && <SDXLConcatButton />}
|
{baseModel === 'sdxl' && <SDXLConcatButton />}
|
||||||
<ShowDynamicPromptsPreviewButton />
|
<ShowDynamicPromptsPreviewButton />
|
||||||
</PromptOverlayButtonWrapper>
|
</PromptOverlayButtonWrapper>
|
||||||
|
{viewMode && (
|
||||||
|
<ViewModePrompt prompt={prompt} presetPrompt={activeStylePreset?.preset_data.positive_prompt || ''} />
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</PromptPopover>
|
</PromptPopover>
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ export const ViewModePrompt = ({ presetPrompt, prompt }: { presetPrompt: string;
|
|||||||
}, [dispatch]);
|
}, [dispatch]);
|
||||||
|
|
||||||
return (
|
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 flexDir="column" onClick={handleExitViewMode} justifyContent="space-between" h="full" padding="8px 10px">
|
||||||
<Flex overflow="scroll">
|
<Flex overflow="scroll">
|
||||||
<Text fontSize="sm" lineHeight="1rem" w="full">
|
<Text fontSize="sm" lineHeight="1rem" w="full">
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { Button, Flex, FormControl, FormLabel, Input, Text } from '@invoke-ai/ui-library';
|
import { Button, Flex, FormControl, FormLabel, Input, Text } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch } from 'app/store/storeHooks';
|
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 { toast } from 'features/toast/toast';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import type { SubmitHandler } from 'react-hook-form';
|
import type { SubmitHandler } from 'react-hook-form';
|
||||||
@ -65,6 +69,7 @@ export const StylePresetForm = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispatch(prefilledFormDataChanged(null));
|
||||||
dispatch(updatingStylePresetIdChanged(null));
|
dispatch(updatingStylePresetIdChanged(null));
|
||||||
dispatch(isModalOpenChanged(false));
|
dispatch(isModalOpenChanged(false));
|
||||||
},
|
},
|
||||||
|
@ -11,7 +11,7 @@ import { toast } from 'features/toast/toast';
|
|||||||
import type { MouseEvent } from 'react';
|
import type { MouseEvent } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
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 type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||||
import { useDeleteStylePresetMutation } from 'services/api/endpoints/stylePresets';
|
import { useDeleteStylePresetMutation } from 'services/api/endpoints/stylePresets';
|
||||||
|
|
||||||
@ -58,6 +58,27 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
[onOpen]
|
[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 () => {
|
const handleDeletePreset = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
await deleteStylePreset(preset.id);
|
await deleteStylePreset(preset.id);
|
||||||
@ -106,25 +127,34 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{preset.type !== 'default' && (
|
<Flex alignItems="center" gap={1}>
|
||||||
<Flex alignItems="center" gap={1}>
|
<IconButton
|
||||||
<IconButton
|
size="sm"
|
||||||
size="sm"
|
variant="ghost"
|
||||||
variant="ghost"
|
aria-label={t('stylePresets.copyTemplate')}
|
||||||
aria-label={t('stylePresets.editTemplate')}
|
onClick={handleClickCopy}
|
||||||
onClick={handleClickEdit}
|
icon={<PiCopyBold />}
|
||||||
icon={<PiPencilBold />}
|
/>
|
||||||
/>
|
{preset.type !== 'default' && (
|
||||||
<IconButton
|
<>
|
||||||
size="sm"
|
<IconButton
|
||||||
variant="ghost"
|
size="sm"
|
||||||
aria-label={t('stylePresets.deleteTemplate')}
|
variant="ghost"
|
||||||
onClick={handleClickDelete}
|
aria-label={t('stylePresets.editTemplate')}
|
||||||
colorScheme="error"
|
onClick={handleClickEdit}
|
||||||
icon={<PiTrashBold />}
|
icon={<PiPencilBold />}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
<IconButton
|
||||||
)}
|
size="sm"
|
||||||
|
variant="ghost"
|
||||||
|
aria-label={t('stylePresets.deleteTemplate')}
|
||||||
|
onClick={handleClickDelete}
|
||||||
|
colorScheme="error"
|
||||||
|
icon={<PiTrashBold />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex flexDir="column" gap={1}>
|
<Flex flexDir="column" gap={1}>
|
||||||
|
Loading…
Reference in New Issue
Block a user