wip apply and calculate prompt with interpolation

This commit is contained in:
Mary Hipp 2024-08-05 19:11:48 -04:00
parent fd7a635777
commit 857d74bbfe
12 changed files with 122 additions and 26 deletions

View File

@ -53,6 +53,7 @@ import type { AppDispatch, RootState } from 'app/store/store';
import { addArchivedOrDeletedBoardListener } from './listeners/addArchivedOrDeletedBoardListener';
import { addEnqueueRequestedUpscale } from './listeners/enqueueRequestedUpscale';
import { addActiveStylePresetChanged } from './listeners/activeStylePresetChanged';
export const listenerMiddleware = createListenerMiddleware();
@ -146,6 +147,7 @@ addAdHocPostProcessingRequestedListener(startAppListening);
// Prompts
addDynamicPromptsListener(startAppListening);
addActiveStylePresetChanged(startAppListening)
addSetDefaultSettingsListener(startAppListening);
addControlAdapterPreprocessor(startAppListening);

View File

@ -0,0 +1,31 @@
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { negativePromptChanged, positivePromptChanged, } from 'features/controlLayers/store/controlLayersSlice';
import { activeStylePresetChanged, calculatedNegPromptChanged, calculatedPosPromptChanged } from '../../../../../features/stylePresets/store/stylePresetSlice';
import { isAnyOf } from '@reduxjs/toolkit';
export const addActiveStylePresetChanged = (startAppListening: AppStartListening) => {
startAppListening({
matcher: isAnyOf(activeStylePresetChanged, positivePromptChanged, negativePromptChanged),
effect: async (action, { dispatch, getState }) => {
const state = getState();
const activeStylePreset = state.stylePreset.activeStylePreset;
const positivePrompt = state.controlLayers.present.positivePrompt
const negativePrompt = state.controlLayers.present.negativePrompt
if (!activeStylePreset) {
return;
}
const { positive_prompt: presetPositivePrompt, negative_prompt: presetNegativePrompt } = activeStylePreset.preset_data;
const calculatedPosPrompt = presetPositivePrompt.includes('{prompt}') ? presetPositivePrompt.replace('{prompt}', positivePrompt) : `${positivePrompt} ${presetPositivePrompt}`
const calculatedNegPrompt = presetNegativePrompt.includes('{prompt}') ? presetNegativePrompt.replace('{prompt}', negativePrompt) : `${negativePrompt} ${presetNegativePrompt}`
dispatch(calculatedPosPromptChanged(calculatedPosPrompt))
dispatch(calculatedNegPromptChanged(calculatedNegPrompt))
},
});
};

View File

@ -28,7 +28,7 @@ import { generationPersistConfig, generationSlice } from 'features/parameters/st
import { upscalePersistConfig, upscaleSlice } from 'features/parameters/store/upscaleSlice';
import { queueSlice } from 'features/queue/store/queueSlice';
import { sdxlPersistConfig, sdxlSlice } from 'features/sdxl/store/sdxlSlice';
import { stylePresetModalSlice } from 'features/stylePresets/store/slice';
import { stylePresetModalSlice } from 'features/stylePresets/store/stylePresetModalSlice';
import { configSlice } from 'features/system/store/configSlice';
import { systemPersistConfig, systemSlice } from 'features/system/store/systemSlice';
import { uiPersistConfig, uiSlice } from 'features/ui/store/uiSlice';
@ -47,6 +47,7 @@ import { actionSanitizer } from './middleware/devtools/actionSanitizer';
import { actionsDenylist } from './middleware/devtools/actionsDenylist';
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
import { listenerMiddleware } from './middleware/listenerMiddleware';
import { stylePresetSlice } from '../../features/stylePresets/store/stylePresetSlice';
const allReducers = {
[canvasSlice.name]: canvasSlice.reducer,
@ -70,7 +71,8 @@ const allReducers = {
[workflowSettingsSlice.name]: workflowSettingsSlice.reducer,
[api.reducerPath]: api.reducer,
[upscaleSlice.name]: upscaleSlice.reducer,
[stylePresetModalSlice.name]: stylePresetModalSlice.reducer
[stylePresetModalSlice.name]: stylePresetModalSlice.reducer,
[stylePresetSlice.name]: stylePresetSlice.reducer
};
const rootReducer = combineReducers(allReducers);

View File

@ -19,12 +19,16 @@ const concatPromptsSelector = createSelector(
export const Prompts = memo(() => {
const shouldConcatPrompts = useAppSelector(concatPromptsSelector);
const calculatedPosPrompt = useAppSelector((s) => s.stylePreset.calculatedPosPrompt);
const calculatedNegPrompt = useAppSelector((s) => s.stylePreset.calculatedNegPrompt);
return (
<Flex flexDir="column" gap={2}>
<StylePresetMenuTrigger />
<ParamPositivePrompt />
<Flex>{calculatedPosPrompt}</Flex>
{!shouldConcatPrompts && <ParamSDXLPositiveStylePrompt />}
<ParamNegativePrompt />
<Flex>{calculatedNegPrompt}</Flex>
{!shouldConcatPrompts && <ParamSDXLNegativeStylePrompt />}
</Flex>
);

View File

@ -1,15 +1,11 @@
import { Button, Flex, FormControl, FormLabel, Input, Textarea } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { isModalOpenChanged,updatingStylePresetChanged } from 'features/stylePresets/store/slice';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/stylePresetModalSlice';
import { toast } from 'features/toast/toast';
import type { ChangeEventHandler} from 'react';
import type { ChangeEventHandler } from 'react';
import { useCallback, useEffect, useState } from 'react';
import type {
StylePresetRecordDTO} from 'services/api/endpoints/stylePresets';
import {
useCreateStylePresetMutation,
useUpdateStylePresetMutation,
} from 'services/api/endpoints/stylePresets';
import type { StylePresetRecordDTO } from 'services/api/endpoints/stylePresets';
import { useCreateStylePresetMutation, useUpdateStylePresetMutation } from 'services/api/endpoints/stylePresets';
export const StylePresetForm = ({ updatingPreset }: { updatingPreset: StylePresetRecordDTO | null }) => {
const [createStylePreset] = useCreateStylePresetMutation();

View File

@ -1,9 +1,10 @@
import { Button, Flex, Text } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/slice';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/stylePresetModalSlice';
import { useCallback } from 'react';
import type { StylePresetRecordDTO} from 'services/api/endpoints/stylePresets';
import type { StylePresetRecordDTO } from 'services/api/endpoints/stylePresets';
import { useDeleteStylePresetMutation } from 'services/api/endpoints/stylePresets';
import { activeStylePresetChanged, isMenuOpenChanged } from '../store/stylePresetSlice';
export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordDTO }) => {
const dispatch = useAppDispatch();
@ -14,6 +15,11 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordDTO }
dispatch(isModalOpenChanged(true));
}, [dispatch, preset]);
const handleClickApply = useCallback(() => {
dispatch(activeStylePresetChanged(preset));
dispatch(isMenuOpenChanged(false));
}, [dispatch, preset]);
const handleDeletePreset = useCallback(async () => {
try {
await deleteStylePreset(preset.id);
@ -39,6 +45,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordDTO }
</Text>
<Button onClick={handleClickEdit}>Edit</Button>
<Button onClick={handleDeletePreset}>Delete</Button>
<Button onClick={handleClickApply}>Apply</Button>
</Flex>
</Flex>
</>

View File

@ -1,6 +1,6 @@
import { Button, Flex, Text } from '@invoke-ai/ui-library';
import { useAppDispatch } from 'app/store/storeHooks';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/slice';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/stylePresetModalSlice';
import { useCallback } from 'react';
import { useListStylePresetsQuery } from 'services/api/endpoints/stylePresets';

View File

@ -1,18 +1,28 @@
import {
Button,
Popover,
PopoverBody,
PopoverContent,
PopoverTrigger,
} from '@invoke-ai/ui-library';
import { Button, Popover, PopoverBody, PopoverContent, PopoverTrigger } from '@invoke-ai/ui-library';
import { StylePresetMenu } from './StylePresetMenu';
import { useAppDispatch, useAppSelector } from '../../../app/store/storeHooks';
import { useCallback } from 'react';
import { isMenuOpenChanged } from '../store/stylePresetSlice';
export const StylePresetMenuTrigger = () => {
const isMenuOpen = useAppSelector((s) => s.stylePreset.isMenuOpen);
const dispatch = useAppDispatch();
const handleClose = useCallback(() => {
dispatch(isMenuOpenChanged(false));
}, [dispatch]);
const handleToggle = useCallback(() => {
dispatch(isMenuOpenChanged(!isMenuOpen));
}, [dispatch, isMenuOpen]);
return (
<Popover isLazy>
<Popover isOpen={isMenuOpen} onClose={handleClose}>
<PopoverTrigger>
<Button size="sm">Style Presets</Button>
<Button size="sm" onClick={handleToggle}>
Style Presets
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverBody>

View File

@ -8,7 +8,7 @@ import {
ModalOverlay,
} from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/slice';
import { isModalOpenChanged, updatingStylePresetChanged } from 'features/stylePresets/store/stylePresetModalSlice';
import { useCallback, useMemo } from 'react';
import { StylePresetForm } from './StylePresetForm';

View File

@ -3,10 +3,10 @@ import { createSlice } from '@reduxjs/toolkit';
import type { RootState } from 'app/store/store';
import type { StylePresetRecordDTO } from 'services/api/endpoints/stylePresets';
import type { StylePresetState } from './types';
import type { StylePresetModalState } from './types';
export const initialState: StylePresetState = {
export const initialState: StylePresetModalState = {
isModalOpen: false,
updatingStylePreset: null,
};

View File

@ -0,0 +1,38 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';
import type { RootState } from 'app/store/store';
import type { StylePresetRecordDTO } from 'services/api/endpoints/stylePresets';
import type { StylePresetState } from './types';
export const initialState: StylePresetState = {
isMenuOpen: false,
activeStylePreset: null,
calculatedPosPrompt: undefined,
calculatedNegPrompt: undefined
};
export const stylePresetSlice = createSlice({
name: 'stylePreset',
initialState: initialState,
reducers: {
isMenuOpenChanged: (state, action: PayloadAction<boolean>) => {
state.isMenuOpen = action.payload;
},
activeStylePresetChanged: (state, action: PayloadAction<StylePresetRecordDTO | null>) => {
state.activeStylePreset = action.payload;
},
calculatedPosPromptChanged: (state, action: PayloadAction<string | undefined>) => {
state.calculatedPosPrompt = action.payload;
},
calculatedNegPromptChanged: (state, action: PayloadAction<string | undefined>) => {
state.calculatedNegPrompt = action.payload;
},
},
});
export const { isMenuOpenChanged, activeStylePresetChanged, calculatedPosPromptChanged, calculatedNegPromptChanged } = stylePresetSlice.actions;
export const selectStylePresetSlice = (state: RootState) => state.stylePreset;

View File

@ -1,8 +1,14 @@
import type { StylePresetRecordDTO } from "services/api/endpoints/stylePresets";
export type StylePresetState = {
export type StylePresetModalState = {
isModalOpen: boolean;
updatingStylePreset: StylePresetRecordDTO | null;
};
export type StylePresetState = {
isMenuOpen: boolean;
activeStylePreset: StylePresetRecordDTO | null;
calculatedPosPrompt?: string
calculatedNegPrompt?: string
}