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",
|
"missingUpscaleModel": "Missing upscale model",
|
||||||
"missingTileControlNetModel": "No valid tile ControlNet models installed"
|
"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": {
|
"upsell": {
|
||||||
"inviteTeammates": "Invite Teammates",
|
"inviteTeammates": "Invite Teammates",
|
||||||
"professional": "Professional",
|
"professional": "Professional",
|
||||||
|
@ -72,7 +72,7 @@ const allReducers = {
|
|||||||
[api.reducerPath]: api.reducer,
|
[api.reducerPath]: api.reducer,
|
||||||
[upscaleSlice.name]: upscaleSlice.reducer,
|
[upscaleSlice.name]: upscaleSlice.reducer,
|
||||||
[stylePresetModalSlice.name]: stylePresetModalSlice.reducer,
|
[stylePresetModalSlice.name]: stylePresetModalSlice.reducer,
|
||||||
[stylePresetSlice.name]: stylePresetSlice.reducer
|
[stylePresetSlice.name]: stylePresetSlice.reducer,
|
||||||
};
|
};
|
||||||
|
|
||||||
const rootReducer = combineReducers(allReducers);
|
const rootReducer = combineReducers(allReducers);
|
||||||
|
@ -6,7 +6,6 @@ import { useCopyImageToClipboard } from 'common/hooks/useCopyImageToClipboard';
|
|||||||
import { useDownloadImage } from 'common/hooks/useDownloadImage';
|
import { useDownloadImage } from 'common/hooks/useDownloadImage';
|
||||||
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice';
|
||||||
import { imagesToChangeSelected, isModalOpenChanged } from 'features/changeBoardModal/store/slice';
|
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 { iiLayerAdded } from 'features/controlLayers/store/controlLayersSlice';
|
||||||
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
import { imagesToDeleteSelected } from 'features/deleteImageModal/store/slice';
|
||||||
import { useImageActions } from 'features/gallery/hooks/useImageActions';
|
import { useImageActions } from 'features/gallery/hooks/useImageActions';
|
||||||
@ -41,8 +40,6 @@ import {
|
|||||||
} from 'react-icons/pi';
|
} from 'react-icons/pi';
|
||||||
import { useStarImagesMutation, useUnstarImagesMutation } from 'services/api/endpoints/images';
|
import { useStarImagesMutation, useUnstarImagesMutation } from 'services/api/endpoints/images';
|
||||||
import type { ImageDTO } from 'services/api/types';
|
import type { ImageDTO } from 'services/api/types';
|
||||||
import { isMenuOpenChanged } from '../../../stylePresets/store/stylePresetSlice';
|
|
||||||
import { createPresetFromImageChanged } from '../../../stylePresets/store/stylePresetModalSlice';
|
|
||||||
|
|
||||||
type SingleSelectionMenuItemsProps = {
|
type SingleSelectionMenuItemsProps = {
|
||||||
imageDTO: ImageDTO;
|
imageDTO: ImageDTO;
|
||||||
@ -200,7 +197,7 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
onClickCapture={createAsPreset}
|
onClickCapture={createAsPreset}
|
||||||
isDisabled={isLoadingMetadata || !hasPrompts}
|
isDisabled={isLoadingMetadata || !hasPrompts}
|
||||||
>
|
>
|
||||||
Create Preset
|
{t('stylePresets.useForTemplate')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuItem icon={<PiShareFatBold />} onClickCapture={handleSendToImageToImage} id="send-to-img2img">
|
<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 { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { useImageUrlToBlob } from 'common/hooks/useImageUrlToBlob';
|
||||||
import { handlers, parseAndRecallAllMetadata, parseAndRecallPrompts } from 'features/metadata/util/handlers';
|
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 { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { useGetImageDTOQuery } from 'services/api/endpoints/images';
|
||||||
import { useDebouncedMetadata } from 'services/api/hooks/useDebouncedMetadata';
|
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) => {
|
export const useImageActions = (image_name?: string) => {
|
||||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||||
@ -15,8 +15,8 @@ export const useImageActions = (image_name?: string) => {
|
|||||||
const [hasSeed, setHasSeed] = useState(false);
|
const [hasSeed, setHasSeed] = useState(false);
|
||||||
const [hasPrompts, setHasPrompts] = useState(false);
|
const [hasPrompts, setHasPrompts] = useState(false);
|
||||||
const imageUrlToBlob = useImageUrlToBlob();
|
const imageUrlToBlob = useImageUrlToBlob();
|
||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch();
|
||||||
const { data: imageDTO } = useGetImageDTOQuery(image_name ?? skipToken)
|
const { data: imageDTO } = useGetImageDTOQuery(image_name ?? skipToken);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const parseMetadata = async () => {
|
const parseMetadata = async () => {
|
||||||
@ -70,15 +70,31 @@ export const useImageActions = (image_name?: string) => {
|
|||||||
|
|
||||||
const createAsPreset = useCallback(async () => {
|
const createAsPreset = useCallback(async () => {
|
||||||
if (image_name && metadata && imageDTO) {
|
if (image_name && metadata && imageDTO) {
|
||||||
const positivePrompt = await handlers.positivePrompt.parse(metadata)
|
const positivePrompt = await handlers.positivePrompt.parse(metadata);
|
||||||
const negativePrompt = await handlers.negativePrompt.parse(metadata)
|
const negativePrompt = await handlers.negativePrompt.parse(metadata);
|
||||||
const imageBlob = await imageUrlToBlob(imageDTO.image_url, 100)
|
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(
|
||||||
dispatch(isModalOpenChanged(true))
|
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,
|
||||||
return { recallAll, remix, recallSeed, recallPrompts, hasMetadata, hasSeed, hasPrompts, isLoadingMetadata, createAsPreset };
|
remix,
|
||||||
|
recallSeed,
|
||||||
|
recallPrompts,
|
||||||
|
hasMetadata,
|
||||||
|
hasSeed,
|
||||||
|
hasPrompts,
|
||||||
|
isLoadingMetadata,
|
||||||
|
createAsPreset,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -98,7 +98,8 @@ export const buildMultidiffusionUpscaleGraph = async (state: RootState): Promise
|
|||||||
let modelNode;
|
let modelNode;
|
||||||
|
|
||||||
if (model.base === 'sdxl') {
|
if (model.base === 'sdxl') {
|
||||||
const { positivePrompt, negativePrompt, positiveStylePrompt, negativeStylePrompt } = getPresetModifiedPrompts(state);
|
const { positivePrompt, negativePrompt, positiveStylePrompt, negativeStylePrompt } =
|
||||||
|
getPresetModifiedPrompts(state);
|
||||||
|
|
||||||
posCondNode = g.addNode({
|
posCondNode = g.addNode({
|
||||||
type: 'sdxl_compel_prompt',
|
type: 'sdxl_compel_prompt',
|
||||||
|
@ -16,7 +16,11 @@ import {
|
|||||||
POSITIVE_CONDITIONING,
|
POSITIVE_CONDITIONING,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||||
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
||||||
|
|
||||||
|
@ -19,7 +19,11 @@ import {
|
|||||||
POSITIVE_CONDITIONING,
|
POSITIVE_CONDITIONING,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||||
|
|
||||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||||
|
@ -23,7 +23,11 @@ import {
|
|||||||
POSITIVE_CONDITIONING,
|
POSITIVE_CONDITIONING,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||||
|
|
||||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||||
|
@ -16,7 +16,11 @@ import {
|
|||||||
SDXL_REFINER_SEAMLESS,
|
SDXL_REFINER_SEAMLESS,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||||
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
||||||
|
|
||||||
|
@ -19,7 +19,11 @@ import {
|
|||||||
SDXL_REFINER_SEAMLESS,
|
SDXL_REFINER_SEAMLESS,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||||
|
|
||||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||||
|
@ -23,7 +23,11 @@ import {
|
|||||||
SDXL_REFINER_SEAMLESS,
|
SDXL_REFINER_SEAMLESS,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 type { ImageDTO, Invocation, NonNullableGraph } from 'services/api/types';
|
||||||
|
|
||||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||||
|
@ -14,7 +14,11 @@ import {
|
|||||||
SDXL_REFINER_SEAMLESS,
|
SDXL_REFINER_SEAMLESS,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 { isNonRefinerMainModelConfig, type NonNullableGraph } from 'services/api/types';
|
||||||
|
|
||||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||||
|
@ -14,7 +14,11 @@ import {
|
|||||||
POSITIVE_CONDITIONING,
|
POSITIVE_CONDITIONING,
|
||||||
SEAMLESS,
|
SEAMLESS,
|
||||||
} from 'features/nodes/util/graph/constants';
|
} 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 { isNonRefinerMainModelConfig, type NonNullableGraph } from 'services/api/types';
|
||||||
|
|
||||||
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
import { addControlNetToLinearGraph } from './addControlNetToLinearGraph';
|
||||||
|
@ -105,10 +105,10 @@ export const buildGenerationTabGraph = async (state: RootState): Promise<GraphTy
|
|||||||
const vaeLoader =
|
const vaeLoader =
|
||||||
vae?.base === model.base
|
vae?.base === model.base
|
||||||
? g.addNode({
|
? g.addNode({
|
||||||
type: 'vae_loader',
|
type: 'vae_loader',
|
||||||
id: VAE_LOADER,
|
id: VAE_LOADER,
|
||||||
vae_model: vae,
|
vae_model: vae,
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
let imageOutput: Invocation<'l2i'> | Invocation<'img_nsfw'> | Invocation<'img_watermark'> = l2i;
|
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 =
|
const vaeLoader =
|
||||||
vae?.base === model.base
|
vae?.base === model.base
|
||||||
? g.addNode({
|
? g.addNode({
|
||||||
type: 'vae_loader',
|
type: 'vae_loader',
|
||||||
id: VAE_LOADER,
|
id: VAE_LOADER,
|
||||||
vae_model: vae,
|
vae_model: vae,
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
let imageOutput: Invocation<'l2i'> | Invocation<'img_nsfw'> | Invocation<'img_watermark'> = l2i;
|
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.
|
* 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 } =
|
const { positivePrompt, negativePrompt, positivePrompt2, negativePrompt2, shouldConcatPrompts } =
|
||||||
state.controlLayers.present;
|
state.controlLayers.present;
|
||||||
const { activeStylePreset } = state.stylePreset
|
const { activeStylePreset } = state.stylePreset;
|
||||||
|
|
||||||
if (activeStylePreset) {
|
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 {
|
return {
|
||||||
positivePrompt: presetModifiedPositivePrompt,
|
positivePrompt: presetModifiedPositivePrompt,
|
||||||
negativePrompt: presetModifiedNegativePrompt,
|
negativePrompt: presetModifiedNegativePrompt,
|
||||||
positiveStylePrompt: shouldConcatPrompts ? presetModifiedPositivePrompt : positivePrompt2,
|
positiveStylePrompt: shouldConcatPrompts ? presetModifiedPositivePrompt : positivePrompt2,
|
||||||
negativeStylePrompt: shouldConcatPrompts ? presetModifiedNegativePrompt : negativePrompt2,
|
negativeStylePrompt: shouldConcatPrompts ? presetModifiedNegativePrompt : negativePrompt2,
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,12 +2,12 @@ import { Box, Textarea } from '@invoke-ai/ui-library';
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { negativePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
import { negativePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
||||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||||
|
import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt';
|
||||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||||
import { usePrompt } from 'features/prompt/usePrompt';
|
import { usePrompt } from 'features/prompt/usePrompt';
|
||||||
import { memo, useCallback, useRef } from 'react';
|
import { memo, useCallback, useRef } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ViewModePrompt } from '../Prompts/ViewModePrompt';
|
|
||||||
|
|
||||||
const DEFAULT_HEIGHT = 20;
|
const DEFAULT_HEIGHT = 20;
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ 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">
|
<Box pos="relative" w="full">
|
||||||
<Textarea
|
<Textarea
|
||||||
id="negativePrompt"
|
id="negativePrompt"
|
||||||
name="negativePrompt"
|
name="negativePrompt"
|
||||||
|
@ -3,6 +3,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|||||||
import { positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
import { positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
||||||
import { ShowDynamicPromptsPreviewButton } from 'features/dynamicPrompts/components/ShowDynamicPromptsPreviewButton';
|
import { ShowDynamicPromptsPreviewButton } from 'features/dynamicPrompts/components/ShowDynamicPromptsPreviewButton';
|
||||||
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper';
|
||||||
|
import { ViewModePrompt } from 'features/parameters/components/Prompts/ViewModePrompt';
|
||||||
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton';
|
||||||
import { PromptPopover } from 'features/prompt/PromptPopover';
|
import { PromptPopover } from 'features/prompt/PromptPopover';
|
||||||
import { usePrompt } from 'features/prompt/usePrompt';
|
import { usePrompt } from 'features/prompt/usePrompt';
|
||||||
@ -11,7 +12,6 @@ import { memo, useCallback, useRef } from 'react';
|
|||||||
import type { HotkeyCallback } from 'react-hotkeys-hook';
|
import type { HotkeyCallback } from 'react-hotkeys-hook';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ViewModePrompt } from '../Prompts/ViewModePrompt';
|
|
||||||
|
|
||||||
const DEFAULT_HEIGHT = 28;
|
const DEFAULT_HEIGHT = 28;
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Flex, Icon, Text, Tooltip, Box } from '@invoke-ai/ui-library';
|
import { Box, Flex, Icon, Text, Tooltip } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../../app/store/storeHooks';
|
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 { useCallback, useMemo } from 'react';
|
||||||
import { PiEyeBold, PiQuestionBold } from 'react-icons/pi';
|
import { PiEyeBold } from 'react-icons/pi';
|
||||||
import { viewModeChanged } from '../../../stylePresets/store/stylePresetSlice';
|
|
||||||
import { getViewModeChunks } from '../../../stylePresets/util/getViewModeChunks';
|
|
||||||
|
|
||||||
export const ViewModePrompt = ({
|
export const ViewModePrompt = ({
|
||||||
presetPrompt,
|
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">
|
<Box position="absolute" top={0} right={0} backgroundColor="rgba(0,0,0,0.75)" padding="2px 5px">
|
||||||
<Flex alignItems="center" gap="1">
|
<Flex alignItems="center" gap="1">
|
||||||
<Tooltip
|
<Tooltip label="This is how your prompt will look with your currently selected preset. To edit your prompt, click anywhere in the text box.">
|
||||||
label={
|
|
||||||
'This is how your prompt will look with your currently selected preset. To edit your prompt, click anywhere in the text box.'
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Flex>
|
<Flex>
|
||||||
<Icon as={PiEyeBold} color="base.500" boxSize="12px" />
|
<Icon as={PiEyeBold} color="base.500" boxSize="12px" />
|
||||||
</Flex>
|
</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 { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { negativePromptChanged, positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
import { negativePromptChanged, positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice';
|
||||||
import { usePresetModifiedPrompts } from 'features/stylePresets/hooks/usePresetModifiedPrompts';
|
import { usePresetModifiedPrompts } from 'features/stylePresets/hooks/usePresetModifiedPrompts';
|
||||||
import { activeStylePresetChanged, viewModeChanged } from 'features/stylePresets/store/stylePresetSlice';
|
import { activeStylePresetChanged, viewModeChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||||
import type { MouseEventHandler } from 'react';
|
import type { MouseEventHandler } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiEyeBold, PiStackSimpleBold, PiXBold } from 'react-icons/pi';
|
import { PiEyeBold, PiStackSimpleBold, PiXBold } from 'react-icons/pi';
|
||||||
|
|
||||||
import StylePresetImage from './StylePresetImage';
|
import StylePresetImage from './StylePresetImage';
|
||||||
|
|
||||||
export const ActiveStylePreset = () => {
|
export const ActiveStylePreset = () => {
|
||||||
const { activeStylePreset, viewMode } = useAppSelector((s) => s.stylePreset);
|
const { activeStylePreset, viewMode } = useAppSelector((s) => s.stylePreset);
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const { presetModifiedPositivePrompt, presetModifiedNegativePrompt } = usePresetModifiedPrompts();
|
const { presetModifiedPositivePrompt, presetModifiedNegativePrompt } = usePresetModifiedPrompts();
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ export const ActiveStylePreset = () => {
|
|||||||
return (
|
return (
|
||||||
<Flex h="25px" alignItems="center">
|
<Flex h="25px" alignItems="center">
|
||||||
<Text fontSize="sm" fontWeight="semibold" color="base.300">
|
<Text fontSize="sm" fontWeight="semibold" color="base.300">
|
||||||
Choose Preset
|
{t('stylePresets.choosePromptTemplate')}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</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 { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { isModalOpenChanged, updatingStylePresetIdChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
import { isModalOpenChanged, 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';
|
||||||
import { useForm } 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 { useCreateStylePresetMutation, useUpdateStylePresetMutation } from 'services/api/endpoints/stylePresets';
|
||||||
|
|
||||||
import { StylePresetPromptField } from './StylePresetPromptField';
|
|
||||||
import { StylePresetImageField } from './StylePresetImageField';
|
import { StylePresetImageField } from './StylePresetImageField';
|
||||||
|
import { StylePresetPromptField } from './StylePresetPromptField';
|
||||||
|
|
||||||
export type StylePresetFormData = {
|
export type StylePresetFormData = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -22,10 +22,11 @@ export const StylePresetForm = ({ updatingStylePresetId }: { updatingStylePreset
|
|||||||
const [createStylePreset] = useCreateStylePresetMutation();
|
const [createStylePreset] = useCreateStylePresetMutation();
|
||||||
const [updateStylePreset] = useUpdateStylePresetMutation();
|
const [updateStylePreset] = useUpdateStylePresetMutation();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const defaultValues = useAppSelector((s) => s.stylePresetModal.prefilledFormData);
|
const defaultValues = useAppSelector((s) => s.stylePresetModal.prefilledFormData);
|
||||||
|
|
||||||
const { handleSubmit, control, formState, reset, register } = useForm<StylePresetFormData>({
|
const { handleSubmit, control, register } = useForm<StylePresetFormData>({
|
||||||
defaultValues: defaultValues || {
|
defaultValues: defaultValues || {
|
||||||
name: '',
|
name: '',
|
||||||
positivePrompt: '',
|
positivePrompt: '',
|
||||||
@ -70,19 +71,18 @@ export const StylePresetForm = ({ updatingStylePresetId }: { updatingStylePreset
|
|||||||
<Flex alignItems="center" gap="4">
|
<Flex alignItems="center" gap="4">
|
||||||
<StylePresetImageField control={control} name="image" />
|
<StylePresetImageField control={control} name="image" />
|
||||||
<FormControl orientation="vertical">
|
<FormControl orientation="vertical">
|
||||||
<FormLabel>Name</FormLabel>
|
<FormLabel>{t('stylePresets.name')}</FormLabel>
|
||||||
<Input size="md" {...register('name')} />
|
<Input size="md" {...register('name')} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<StylePresetPromptField label="Positive Prompt" control={control} name="positivePrompt" />
|
<StylePresetPromptField label="Positive Prompt" control={control} name="positivePrompt" />
|
||||||
<StylePresetPromptField label="Negative Prompt" control={control} name="negativePrompt" />
|
<StylePresetPromptField label="Negative Prompt" control={control} name="negativePrompt" />
|
||||||
<Text variant="subtext">
|
<Text variant="subtext">{t('stylePresets.placeholderDirections')}</Text>
|
||||||
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>
|
|
||||||
|
|
||||||
<Button onClick={handleSubmit(handleClickSave)}>Save</Button>
|
<Flex justifyContent="flex-end">
|
||||||
|
<Button onClick={handleSubmit(handleClickSave)}>{t('common.save')}</Button>
|
||||||
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import { Tooltip, Flex, Button, Icon, Box, Image, IconButton } from '@invoke-ai/ui-library';
|
import { Box, Button, Flex, Icon, IconButton, Image, Tooltip } from '@invoke-ai/ui-library';
|
||||||
import { t } from 'i18next';
|
import { useCallback } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
|
||||||
import { useDropzone } from 'react-dropzone';
|
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 { 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>) => {
|
export const StylePresetImageField = (props: UseControllerProps<StylePresetFormData>) => {
|
||||||
const { field } = useController(props);
|
const { field } = useController(props);
|
||||||
|
const { t } = useTranslation();
|
||||||
const onDropAccepted = useCallback(
|
const onDropAccepted = useCallback(
|
||||||
(files: File[]) => {
|
(files: File[]) => {
|
||||||
const file = files[0];
|
const file = files[0];
|
||||||
@ -15,12 +18,12 @@ export const StylePresetImageField = (props: UseControllerProps<StylePresetFormD
|
|||||||
field.onChange(file);
|
field.onChange(file);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[field, t]
|
[field]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleResetImage = useCallback(() => {
|
const handleResetImage = useCallback(() => {
|
||||||
field.onChange(null);
|
field.onChange(null);
|
||||||
}, []);
|
}, [field]);
|
||||||
|
|
||||||
const { getInputProps, getRootProps } = useDropzone({
|
const { getInputProps, getRootProps } = useDropzone({
|
||||||
accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] },
|
accept: { 'image/png': ['.png'], 'image/jpeg': ['.jpg', '.jpeg', '.png'] },
|
||||||
@ -46,8 +49,8 @@ export const StylePresetImageField = (props: UseControllerProps<StylePresetFormD
|
|||||||
insetInlineEnd={0}
|
insetInlineEnd={0}
|
||||||
insetBlockStart={0}
|
insetBlockStart={0}
|
||||||
onClick={handleResetImage}
|
onClick={handleResetImage}
|
||||||
aria-label={t('modelManager.deleteModelImage')}
|
aria-label={t('stylePresets.deleteImage')}
|
||||||
tooltip={t('modelManager.deleteModelImage')}
|
tooltip={t('stylePresets.deleteImage')}
|
||||||
icon={<PiArrowCounterClockwiseBold />}
|
icon={<PiArrowCounterClockwiseBold />}
|
||||||
size="md"
|
size="md"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
@ -58,7 +61,7 @@ export const StylePresetImageField = (props: UseControllerProps<StylePresetFormD
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip label={t('modelManager.uploadImage')}>
|
<Tooltip label={t('stylePresets.uploadImage')}>
|
||||||
<Flex
|
<Flex
|
||||||
as={Button}
|
as={Button}
|
||||||
w={65}
|
w={65}
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
import { Badge, ConfirmationAlertDialog, Flex, IconButton, Text, useDisclosure } from '@invoke-ai/ui-library';
|
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 { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { useImageUrlToBlob } from 'common/hooks/useImageUrlToBlob';
|
||||||
import {
|
import {
|
||||||
isModalOpenChanged,
|
isModalOpenChanged,
|
||||||
prefilledFormDataChanged,
|
prefilledFormDataChanged,
|
||||||
updatingStylePresetIdChanged,
|
updatingStylePresetIdChanged,
|
||||||
} from 'features/stylePresets/store/stylePresetModalSlice';
|
} from 'features/stylePresets/store/stylePresetModalSlice';
|
||||||
import { activeStylePresetChanged, isMenuOpenChanged } from 'features/stylePresets/store/stylePresetSlice';
|
import { activeStylePresetChanged, isMenuOpenChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||||
|
import { toast } from 'features/toast/toast';
|
||||||
|
import type { MouseEvent } from 'react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPencilBold, PiTrashBold } from 'react-icons/pi';
|
import { 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';
|
||||||
|
|
||||||
import StylePresetImage from './StylePresetImage';
|
import StylePresetImage from './StylePresetImage';
|
||||||
import { useImageUrlToBlob } from 'common/hooks/useImageUrlToBlob';
|
|
||||||
|
|
||||||
export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithImage }) => {
|
export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithImage }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -20,6 +23,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
const activeStylePreset = useAppSelector((s) => s.stylePreset.activeStylePreset);
|
const activeStylePreset = useAppSelector((s) => s.stylePreset.activeStylePreset);
|
||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const imageUrlToBlob = useImageUrlToBlob();
|
const imageUrlToBlob = useImageUrlToBlob();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleClickEdit = useCallback(
|
const handleClickEdit = useCallback(
|
||||||
async (e: MouseEvent<HTMLButtonElement>) => {
|
async (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
@ -43,7 +47,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
dispatch(updatingStylePresetIdChanged(preset.id));
|
dispatch(updatingStylePresetIdChanged(preset.id));
|
||||||
dispatch(isModalOpenChanged(true));
|
dispatch(isModalOpenChanged(true));
|
||||||
},
|
},
|
||||||
[dispatch, preset]
|
[dispatch, preset, imageUrlToBlob]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClickApply = useCallback(async () => {
|
const handleClickApply = useCallback(async () => {
|
||||||
@ -56,14 +60,23 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
onOpen();
|
onOpen();
|
||||||
},
|
},
|
||||||
[dispatch, preset]
|
[onOpen]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleDeletePreset = useCallback(async () => {
|
const handleDeletePreset = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
await deleteStylePreset(preset.id);
|
await deleteStylePreset(preset.id);
|
||||||
} catch (error) {}
|
toast({
|
||||||
}, [preset]);
|
status: 'success',
|
||||||
|
title: t('stylePresets.templateDeleted'),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
toast({
|
||||||
|
status: 'error',
|
||||||
|
title: t('stylePresets.unableToDeleteTemplate'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [preset, t, deleteStylePreset]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -92,7 +105,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
bg="transparent"
|
bg="transparent"
|
||||||
flexShrink={0}
|
flexShrink={0}
|
||||||
>
|
>
|
||||||
Active
|
{t('stylePresets.active')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -101,14 +114,14 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
aria-label="Edit"
|
aria-label={t('stylePresets.editTemplate')}
|
||||||
onClick={handleClickEdit}
|
onClick={handleClickEdit}
|
||||||
icon={<PiPencilBold />}
|
icon={<PiPencilBold />}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
aria-label="Delete"
|
aria-label={t('stylePresets.deleteTemplate')}
|
||||||
onClick={handleClickDelete}
|
onClick={handleClickDelete}
|
||||||
colorScheme="error"
|
colorScheme="error"
|
||||||
icon={<PiTrashBold />}
|
icon={<PiTrashBold />}
|
||||||
@ -116,16 +129,16 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex flexDir="column">
|
<Flex flexDir="column" gap="1">
|
||||||
<Text fontSize="xs">
|
<Text fontSize="xs">
|
||||||
<Text as="span" fontWeight="semibold">
|
<Text as="span" fontWeight="semibold">
|
||||||
Positive prompt:
|
{t('stylePresets.positivePrompt')}:
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
{preset.preset_data.positive_prompt}
|
{preset.preset_data.positive_prompt}
|
||||||
</Text>
|
</Text>
|
||||||
<Text fontSize="xs">
|
<Text fontSize="xs">
|
||||||
<Text as="span" fontWeight="semibold">
|
<Text as="span" fontWeight="semibold">
|
||||||
Negative prompt:
|
{t('stylePresets.negativePrompt')}:
|
||||||
</Text>{' '}
|
</Text>{' '}
|
||||||
{preset.preset_data.negative_prompt}
|
{preset.preset_data.negative_prompt}
|
||||||
</Text>
|
</Text>
|
||||||
@ -135,12 +148,11 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
|||||||
<ConfirmationAlertDialog
|
<ConfirmationAlertDialog
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
title={'Delete preset'}
|
title={t('stylePresets.deleteTemplate')}
|
||||||
acceptCallback={handleDeletePreset}
|
acceptCallback={handleDeletePreset}
|
||||||
acceptButtonText={'Delete'}
|
acceptButtonText="Delete"
|
||||||
>
|
>
|
||||||
<p>{'Delete Preset?'}</p>
|
<p>{t('stylePresets.deleteTemplate2')}</p>
|
||||||
<br />
|
|
||||||
</ConfirmationAlertDialog>
|
</ConfirmationAlertDialog>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
updatingStylePresetIdChanged,
|
updatingStylePresetIdChanged,
|
||||||
} from 'features/stylePresets/store/stylePresetModalSlice';
|
} from 'features/stylePresets/store/stylePresetModalSlice';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { PiPlusBold } from 'react-icons/pi';
|
import { PiPlusBold } from 'react-icons/pi';
|
||||||
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||||
import { useListStylePresetsQuery } from 'services/api/endpoints/stylePresets';
|
import { useListStylePresetsQuery } from 'services/api/endpoints/stylePresets';
|
||||||
@ -42,6 +43,7 @@ export const StylePresetMenu = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleClickAddNew = useCallback(() => {
|
const handleClickAddNew = useCallback(() => {
|
||||||
dispatch(prefilledFormDataChanged(null));
|
dispatch(prefilledFormDataChanged(null));
|
||||||
@ -67,13 +69,13 @@ export const StylePresetMenu = () => {
|
|||||||
|
|
||||||
{data.presets.length === 0 && data.defaultPresets.length === 0 && (
|
{data.presets.length === 0 && data.defaultPresets.length === 0 && (
|
||||||
<Text m="20px" textAlign="center">
|
<Text m="20px" textAlign="center">
|
||||||
No matching presets
|
{t('stylePrests.noMatchingTemplates')}
|
||||||
</Text>
|
</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>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,17 +10,19 @@ import {
|
|||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { isModalOpenChanged, updatingStylePresetIdChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
import { isModalOpenChanged, updatingStylePresetIdChanged } from 'features/stylePresets/store/stylePresetModalSlice';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { StylePresetForm } from './StylePresetForm';
|
import { StylePresetForm } from './StylePresetForm';
|
||||||
|
|
||||||
export const StylePresetModal = () => {
|
export const StylePresetModal = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
const isModalOpen = useAppSelector((s) => s.stylePresetModal.isModalOpen);
|
const isModalOpen = useAppSelector((s) => s.stylePresetModal.isModalOpen);
|
||||||
const updatingStylePresetId = useAppSelector((s) => s.stylePresetModal.updatingStylePresetId);
|
const updatingStylePresetId = useAppSelector((s) => s.stylePresetModal.updatingStylePresetId);
|
||||||
|
|
||||||
const modalTitle = useMemo(() => {
|
const modalTitle = useMemo(() => {
|
||||||
return updatingStylePresetId ? `Update Style Preset` : `Create Style Preset`;
|
return updatingStylePresetId ? t('stylePresets.updatePromptTemplate') : t('stylePresets.createPromptTemplate');
|
||||||
}, [updatingStylePresetId]);
|
}, [updatingStylePresetId, t]);
|
||||||
|
|
||||||
const handleCloseModal = useCallback(() => {
|
const handleCloseModal = useCallback(() => {
|
||||||
dispatch(updatingStylePresetIdChanged(null));
|
dispatch(updatingStylePresetIdChanged(null));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Flex, FormControl, FormLabel, IconButton, Textarea } from '@invoke-ai/ui-library';
|
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 type { ChangeEventHandler } from 'react';
|
||||||
import { useCallback, useMemo, useRef } from 'react';
|
import { useCallback, useMemo, useRef } from 'react';
|
||||||
import type { UseControllerProps } from 'react-hook-form';
|
import type { UseControllerProps } from 'react-hook-form';
|
||||||
@ -6,7 +7,6 @@ import { useController } from 'react-hook-form';
|
|||||||
import { PiBracketsCurlyBold } from 'react-icons/pi';
|
import { PiBracketsCurlyBold } from 'react-icons/pi';
|
||||||
|
|
||||||
import type { StylePresetFormData } from './StylePresetForm';
|
import type { StylePresetFormData } from './StylePresetForm';
|
||||||
import { PRESET_PLACEHOLDER } from '../hooks/usePresetModifiedPrompts';
|
|
||||||
|
|
||||||
interface Props extends UseControllerProps<StylePresetFormData> {
|
interface Props extends UseControllerProps<StylePresetFormData> {
|
||||||
label: string;
|
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) => {
|
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 = () => {
|
export const usePresetModifiedPrompts = () => {
|
||||||
const activeStylePreset = useAppSelector(s => s.stylePreset.activeStylePreset)
|
const activeStylePreset = useAppSelector((s) => s.stylePreset.activeStylePreset);
|
||||||
const { positivePrompt, negativePrompt } = useAppSelector(s => s.controlLayers.present)
|
const { positivePrompt, negativePrompt } = useAppSelector((s) => s.controlLayers.present);
|
||||||
|
|
||||||
if (!activeStylePreset) {
|
if (!activeStylePreset) {
|
||||||
return { presetModifiedPositivePrompt: positivePrompt, presetModifiedNegativePrompt: negativePrompt }
|
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 type { PayloadAction } from '@reduxjs/toolkit';
|
||||||
import { createSlice } from '@reduxjs/toolkit';
|
import { createSlice } from '@reduxjs/toolkit';
|
||||||
import type { RootState } from 'app/store/store';
|
import type { RootState } from 'app/store/store';
|
||||||
|
import type { StylePresetFormData } from 'features/stylePresets/components/StylePresetForm';
|
||||||
|
|
||||||
import type { StylePresetModalState } from './types';
|
import type { StylePresetModalState } from './types';
|
||||||
import { StylePresetFormData } from '../components/StylePresetForm';
|
|
||||||
|
|
||||||
|
|
||||||
export const initialState: StylePresetModalState = {
|
export const initialState: StylePresetModalState = {
|
||||||
isModalOpen: false,
|
isModalOpen: false,
|
||||||
updatingStylePresetId: null,
|
updatingStylePresetId: null,
|
||||||
prefilledFormData: null
|
prefilledFormData: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const stylePresetModalSlice = createSlice({
|
export const stylePresetModalSlice = createSlice({
|
||||||
name: 'stylePresetModal',
|
name: 'stylePresetModal',
|
||||||
initialState: initialState,
|
initialState: initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
isModalOpenChanged: (state, action: PayloadAction<boolean>) => {
|
isModalOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isModalOpen = action.payload;
|
state.isModalOpen = action.payload;
|
||||||
},
|
|
||||||
updatingStylePresetIdChanged: (state, action: PayloadAction<string | null>) => {
|
|
||||||
state.updatingStylePresetId = action.payload;
|
|
||||||
},
|
|
||||||
prefilledFormDataChanged: (state, action: PayloadAction<StylePresetFormData | null>) => {
|
|
||||||
state.prefilledFormData = 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;
|
export const selectStylePresetModalSlice = (state: RootState) => state.stylePresetModal;
|
||||||
|
@ -5,34 +5,33 @@ import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePre
|
|||||||
|
|
||||||
import type { StylePresetState } from './types';
|
import type { StylePresetState } from './types';
|
||||||
|
|
||||||
|
|
||||||
export const initialState: StylePresetState = {
|
export const initialState: StylePresetState = {
|
||||||
isMenuOpen: false,
|
isMenuOpen: false,
|
||||||
activeStylePreset: null,
|
activeStylePreset: null,
|
||||||
searchTerm: "",
|
searchTerm: '',
|
||||||
viewMode: false
|
viewMode: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const stylePresetSlice = createSlice({
|
export const stylePresetSlice = createSlice({
|
||||||
name: 'stylePreset',
|
name: 'stylePreset',
|
||||||
initialState: initialState,
|
initialState: initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
isMenuOpenChanged: (state, action: PayloadAction<boolean>) => {
|
isMenuOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isMenuOpen = action.payload;
|
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;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
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;
|
export const selectStylePresetSlice = (state: RootState) => state.stylePreset;
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
import type { StylePresetRecordWithImage } from "services/api/endpoints/stylePresets";
|
import type { StylePresetFormData } from 'features/stylePresets/components/StylePresetForm';
|
||||||
import { StylePresetFormData } from "../components/StylePresetForm";
|
import type { StylePresetRecordWithImage } from 'services/api/endpoints/stylePresets';
|
||||||
|
|
||||||
export type StylePresetModalState = {
|
export type StylePresetModalState = {
|
||||||
isModalOpen: boolean;
|
isModalOpen: boolean;
|
||||||
updatingStylePresetId: string | null;
|
updatingStylePresetId: string | null;
|
||||||
prefilledFormData: StylePresetFormData | null
|
prefilledFormData: StylePresetFormData | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export type StylePresetState = {
|
export type StylePresetState = {
|
||||||
isMenuOpen: boolean;
|
isMenuOpen: boolean;
|
||||||
activeStylePreset: StylePresetRecordWithImage | null;
|
activeStylePreset: StylePresetRecordWithImage | null;
|
||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
viewMode: boolean;
|
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) => {
|
export const getViewModeChunks = (currentPrompt: string, presetPrompt?: string) => {
|
||||||
if (!presetPrompt || !presetPrompt.length) {
|
if (!presetPrompt || !presetPrompt.length) {
|
||||||
|
@ -9,11 +9,11 @@ import { ControlSettingsAccordion } from 'features/settingsAccordions/components
|
|||||||
import { GenerationSettingsAccordion } from 'features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion';
|
import { GenerationSettingsAccordion } from 'features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion';
|
||||||
import { ImageSettingsAccordion } from 'features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion';
|
import { ImageSettingsAccordion } from 'features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion';
|
||||||
import { RefinerSettingsAccordion } from 'features/settingsAccordions/components/RefinerSettingsAccordion/RefinerSettingsAccordion';
|
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 { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { StylePresetMenu } from '../../../stylePresets/components/StylePresetMenu';
|
|
||||||
import { StylePresetMenuTrigger } from '../../../stylePresets/components/StylePresetMenuTrigger';
|
|
||||||
|
|
||||||
const overlayScrollbarsStyles: CSSProperties = {
|
const overlayScrollbarsStyles: CSSProperties = {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||||
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
||||||
import QueueControls from 'features/queue/components/QueueControls';
|
import QueueControls from 'features/queue/components/QueueControls';
|
||||||
import { AdvancedSettingsAccordion } from 'features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion';
|
import { AdvancedSettingsAccordion } from 'features/settingsAccordions/components/AdvancedSettingsAccordion/AdvancedSettingsAccordion';
|
||||||
import { GenerationSettingsAccordion } from 'features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion';
|
import { GenerationSettingsAccordion } from 'features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion';
|
||||||
import { UpscaleSettingsAccordion } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion';
|
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 { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import { memo } 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 = {
|
const overlayScrollbarsStyles: CSSProperties = {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
@ -2,7 +2,8 @@ import type { paths } from 'services/api/schema';
|
|||||||
|
|
||||||
import { api, buildV1Url, LIST_TAG } from '..';
|
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
|
* Builds an endpoint URL for the style_presets router
|
||||||
@ -60,7 +61,9 @@ export const stylePresetsApi = api.injectEndpoints({
|
|||||||
}),
|
}),
|
||||||
updateStylePreset: build.mutation<
|
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']['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 }) => {
|
query: ({ id, name, positive_prompt, negative_prompt, image }) => {
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
@ -72,12 +75,11 @@ export const stylePresetsApi = api.injectEndpoints({
|
|||||||
formData.append('positive_prompt', positive_prompt);
|
formData.append('positive_prompt', positive_prompt);
|
||||||
formData.append('negative_prompt', negative_prompt);
|
formData.append('negative_prompt', negative_prompt);
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url: buildStylePresetsUrl(`i/${id}`),
|
url: buildStylePresetsUrl(`i/${id}`),
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: formData
|
body: formData,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
invalidatesTags: (response, error, { id }) => [
|
invalidatesTags: (response, error, { id }) => [
|
||||||
{ type: 'StylePreset', id: LIST_TAG },
|
{ type: 'StylePreset', id: LIST_TAG },
|
||||||
|
Loading…
Reference in New Issue
Block a user