mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
UI more pr feedback
This commit is contained in:
parent
41c3e73a3c
commit
1e547ef912
@ -1,11 +1,12 @@
|
||||
import { Badge, ConfirmationAlertDialog, Flex, IconButton, Text, useDisclosure } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
|
||||
import {
|
||||
isModalOpenChanged,
|
||||
prefilledFormDataChanged,
|
||||
updatingStylePresetIdChanged,
|
||||
} from 'features/stylePresets/store/stylePresetModalSlice';
|
||||
import { activeStylePresetIdChanged, isMenuOpenChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { activeStylePresetIdChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { toast } from 'features/toast/toast';
|
||||
import type { MouseEvent } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
@ -46,7 +47,7 @@ export const StylePresetListItem = ({ preset }: { preset: StylePresetRecordWithI
|
||||
|
||||
const handleClickApply = useCallback(async () => {
|
||||
dispatch(activeStylePresetIdChanged(preset.id));
|
||||
dispatch(isMenuOpenChanged(false));
|
||||
$isMenuOpen.set(false);
|
||||
}, [dispatch, preset.id]);
|
||||
|
||||
const handleClickDelete = useCallback(
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Flex, IconButton } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { isMenuOpenChanged } from 'features/stylePresets/store/stylePresetSlice';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiCaretDownBold } from 'react-icons/pi';
|
||||
@ -8,13 +8,12 @@ import { PiCaretDownBold } from 'react-icons/pi';
|
||||
import { ActiveStylePreset } from './ActiveStylePreset';
|
||||
|
||||
export const StylePresetMenuTrigger = () => {
|
||||
const isMenuOpen = useAppSelector((s) => s.stylePreset.isMenuOpen);
|
||||
const dispatch = useAppDispatch();
|
||||
const isMenuOpen = useStore($isMenuOpen);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleToggle = useCallback(() => {
|
||||
dispatch(isMenuOpenChanged(!isMenuOpen));
|
||||
}, [dispatch, isMenuOpen]);
|
||||
$isMenuOpen.set(!isMenuOpen);
|
||||
}, [isMenuOpen]);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
|
@ -5,7 +5,7 @@ export const PRESET_PLACEHOLDER = `[prompt]`;
|
||||
|
||||
export const buildPresetModifiedPrompt = (presetPrompt: string, currentPrompt: string) => {
|
||||
return presetPrompt.includes(PRESET_PLACEHOLDER)
|
||||
? presetPrompt.replace(new RegExp(PRESET_PLACEHOLDER), currentPrompt)
|
||||
? presetPrompt.replace(PRESET_PLACEHOLDER, currentPrompt)
|
||||
: `${currentPrompt} ${presetPrompt}`;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,6 @@
|
||||
import { atom } from 'nanostores';
|
||||
|
||||
/**
|
||||
* Tracks whether or not the style preset menu is open.
|
||||
*/
|
||||
export const $isMenuOpen = atom<boolean>(false);
|
@ -5,7 +5,6 @@ import type { PersistConfig } from 'app/store/store';
|
||||
import type { StylePresetState } from './types';
|
||||
|
||||
const initialState: StylePresetState = {
|
||||
isMenuOpen: false,
|
||||
activeStylePresetId: null,
|
||||
searchTerm: '',
|
||||
viewMode: false,
|
||||
@ -15,9 +14,6 @@ export const stylePresetSlice = createSlice({
|
||||
name: 'stylePreset',
|
||||
initialState: initialState,
|
||||
reducers: {
|
||||
isMenuOpenChanged: (state, action: PayloadAction<boolean>) => {
|
||||
state.isMenuOpen = action.payload;
|
||||
},
|
||||
activeStylePresetIdChanged: (state, action: PayloadAction<string | null>) => {
|
||||
state.activeStylePresetId = action.payload;
|
||||
},
|
||||
@ -30,8 +26,7 @@ export const stylePresetSlice = createSlice({
|
||||
},
|
||||
});
|
||||
|
||||
export const { isMenuOpenChanged, activeStylePresetIdChanged, searchTermChanged, viewModeChanged } =
|
||||
stylePresetSlice.actions;
|
||||
export const { activeStylePresetIdChanged, searchTermChanged, viewModeChanged } = stylePresetSlice.actions;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
const migrateStylePresetState = (state: any): any => {
|
||||
|
@ -12,7 +12,6 @@ export type PrefilledFormData = {
|
||||
};
|
||||
|
||||
export type StylePresetState = {
|
||||
isMenuOpen: boolean;
|
||||
activeStylePresetId: string | null;
|
||||
searchTerm: string;
|
||||
viewMode: boolean;
|
||||
|
@ -3,7 +3,8 @@ export const getViewModeChunks = (currentPrompt: string, presetPrompt?: string):
|
||||
if (!presetPrompt || !presetPrompt.length) {
|
||||
return ['', currentPrompt, ''];
|
||||
}
|
||||
const chunks = presetPrompt.split(PRESET_PLACEHOLDER);
|
||||
const [firstPart, ...remainingParts] = presetPrompt.split(PRESET_PLACEHOLDER);
|
||||
const chunks = [firstPart, remainingParts.join(PRESET_PLACEHOLDER)];
|
||||
if (chunks.length === 1) {
|
||||
return ['', currentPrompt, chunks[0] ?? ''];
|
||||
} else {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
||||
@ -11,6 +12,7 @@ import { ImageSettingsAccordion } from 'features/settingsAccordions/components/I
|
||||
import { RefinerSettingsAccordion } from 'features/settingsAccordions/components/RefinerSettingsAccordion/RefinerSettingsAccordion';
|
||||
import { StylePresetMenu } from 'features/stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from 'features/stylePresets/components/StylePresetMenuTrigger';
|
||||
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo } from 'react';
|
||||
@ -22,7 +24,7 @@ const overlayScrollbarsStyles: CSSProperties = {
|
||||
|
||||
const ParametersPanelCanvas = () => {
|
||||
const isSDXL = useAppSelector((s) => s.generation.model?.base === 'sdxl');
|
||||
const isMenuOpen = useAppSelector((s) => s.stylePreset.isMenuOpen);
|
||||
const isMenuOpen = useStore($isMenuOpen);
|
||||
|
||||
return (
|
||||
<Flex w="full" h="full" flexDir="column" gap={2}>
|
||||
@ -30,25 +32,24 @@ const ParametersPanelCanvas = () => {
|
||||
<StylePresetMenuTrigger />
|
||||
<Flex w="full" h="full" position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||
{isMenuOpen ? (
|
||||
{isMenuOpen && (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<StylePresetMenu />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
) : (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<Prompts />
|
||||
<ImageSettingsAccordion />
|
||||
<GenerationSettingsAccordion />
|
||||
<ControlSettingsAccordion />
|
||||
<CompositingSettingsAccordion />
|
||||
{isSDXL && <RefinerSettingsAccordion />}
|
||||
<AdvancedSettingsAccordion />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
)}
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<Prompts />
|
||||
<ImageSettingsAccordion />
|
||||
<GenerationSettingsAccordion />
|
||||
<ControlSettingsAccordion />
|
||||
<CompositingSettingsAccordion />
|
||||
{isSDXL && <RefinerSettingsAccordion />}
|
||||
<AdvancedSettingsAccordion />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import type { ChakraProps } from '@invoke-ai/ui-library';
|
||||
import { Box, Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { ControlLayersPanelContent } from 'features/controlLayers/components/ControlLayersPanelContent';
|
||||
@ -15,6 +16,7 @@ import { ImageSettingsAccordion } from 'features/settingsAccordions/components/I
|
||||
import { RefinerSettingsAccordion } from 'features/settingsAccordions/components/RefinerSettingsAccordion/RefinerSettingsAccordion';
|
||||
import { StylePresetMenu } from 'features/stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from 'features/stylePresets/components/StylePresetMenuTrigger';
|
||||
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
|
||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
@ -61,7 +63,7 @@ const ParametersPanelTextToImage = () => {
|
||||
);
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const isMenuOpen = useAppSelector((s) => s.stylePreset.isMenuOpen);
|
||||
const isMenuOpen = useStore($isMenuOpen);
|
||||
|
||||
return (
|
||||
<Flex w="full" h="full" flexDir="column" gap={2}>
|
||||
@ -69,57 +71,56 @@ const ParametersPanelTextToImage = () => {
|
||||
<StylePresetMenuTrigger />
|
||||
<Flex w="full" h="full" position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0} ref={ref}>
|
||||
{isMenuOpen ? (
|
||||
{isMenuOpen && (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<StylePresetMenu />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
) : (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<Prompts />
|
||||
<Tabs
|
||||
defaultIndex={0}
|
||||
variant="enclosed"
|
||||
display="flex"
|
||||
flexDir="column"
|
||||
w="full"
|
||||
h="full"
|
||||
gap={2}
|
||||
onChange={onChangeTabs}
|
||||
>
|
||||
<TabList gap={2} fontSize="sm" borderColor="base.800">
|
||||
<Tab sx={baseStyles} _selected={selectedStyles} data-testid="generation-tab-settings-tab-button">
|
||||
{t('common.settingsLabel')}
|
||||
</Tab>
|
||||
<Tab
|
||||
sx={baseStyles}
|
||||
_selected={selectedStyles}
|
||||
data-testid="generation-tab-control-layers-tab-button"
|
||||
>
|
||||
{controlLayersTitle}
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanels w="full" h="full">
|
||||
<TabPanel p={0} w="full" h="full">
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<ImageSettingsAccordion />
|
||||
<GenerationSettingsAccordion />
|
||||
{activeTabName !== 'generation' && <ControlSettingsAccordion />}
|
||||
{activeTabName === 'canvas' && <CompositingSettingsAccordion />}
|
||||
{isSDXL && <RefinerSettingsAccordion />}
|
||||
<AdvancedSettingsAccordion />
|
||||
</Flex>
|
||||
</TabPanel>
|
||||
<TabPanel p={0} w="full" h="full">
|
||||
<ControlLayersPanelContent />
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
)}
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<Prompts />
|
||||
<Tabs
|
||||
defaultIndex={0}
|
||||
variant="enclosed"
|
||||
display="flex"
|
||||
flexDir="column"
|
||||
w="full"
|
||||
h="full"
|
||||
gap={2}
|
||||
onChange={onChangeTabs}
|
||||
>
|
||||
<TabList gap={2} fontSize="sm" borderColor="base.800">
|
||||
<Tab sx={baseStyles} _selected={selectedStyles} data-testid="generation-tab-settings-tab-button">
|
||||
{t('common.settingsLabel')}
|
||||
</Tab>
|
||||
<Tab
|
||||
sx={baseStyles}
|
||||
_selected={selectedStyles}
|
||||
data-testid="generation-tab-control-layers-tab-button"
|
||||
>
|
||||
{controlLayersTitle}
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanels w="full" h="full">
|
||||
<TabPanel p={0} w="full" h="full">
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<ImageSettingsAccordion />
|
||||
<GenerationSettingsAccordion />
|
||||
{activeTabName !== 'generation' && <ControlSettingsAccordion />}
|
||||
{activeTabName === 'canvas' && <CompositingSettingsAccordion />}
|
||||
{isSDXL && <RefinerSettingsAccordion />}
|
||||
<AdvancedSettingsAccordion />
|
||||
</Flex>
|
||||
</TabPanel>
|
||||
<TabPanel p={0} w="full" h="full">
|
||||
<ControlLayersPanelContent />
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Box, Flex } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
||||
import QueueControls from 'features/queue/components/QueueControls';
|
||||
@ -8,6 +8,7 @@ import { GenerationSettingsAccordion } from 'features/settingsAccordions/compone
|
||||
import { UpscaleSettingsAccordion } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion';
|
||||
import { StylePresetMenu } from 'features/stylePresets/components/StylePresetMenu';
|
||||
import { StylePresetMenuTrigger } from 'features/stylePresets/components/StylePresetMenuTrigger';
|
||||
import { $isMenuOpen } from 'features/stylePresets/store/isMenuOpen';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
import { memo } from 'react';
|
||||
@ -18,29 +19,28 @@ const overlayScrollbarsStyles: CSSProperties = {
|
||||
};
|
||||
|
||||
const ParametersPanelUpscale = () => {
|
||||
const isMenuOpen = useAppSelector((s) => s.stylePreset.isMenuOpen);
|
||||
const isMenuOpen = useStore($isMenuOpen);
|
||||
return (
|
||||
<Flex w="full" h="full" flexDir="column" gap={2}>
|
||||
<QueueControls />
|
||||
<StylePresetMenuTrigger />
|
||||
<Flex w="full" h="full" position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||
{isMenuOpen ? (
|
||||
{isMenuOpen && (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<StylePresetMenu />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
) : (
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<Prompts />
|
||||
<UpscaleSettingsAccordion />
|
||||
<GenerationSettingsAccordion />
|
||||
<AdvancedSettingsAccordion />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
)}
|
||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||
<Prompts />
|
||||
<UpscaleSettingsAccordion />
|
||||
<GenerationSettingsAccordion />
|
||||
<AdvancedSettingsAccordion />
|
||||
</Flex>
|
||||
</OverlayScrollbarsComponent>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
@ -44,9 +44,8 @@ export const stylePresetsApi = api.injectEndpoints({
|
||||
if (image) {
|
||||
formData.append('image', image);
|
||||
}
|
||||
formData.append('name', name);
|
||||
formData.append('positive_prompt', positive_prompt);
|
||||
formData.append('negative_prompt', negative_prompt);
|
||||
|
||||
formData.append('data', JSON.stringify({ name, positive_prompt, negative_prompt }));
|
||||
|
||||
return {
|
||||
url: buildStylePresetsUrl(),
|
||||
@ -70,10 +69,7 @@ export const stylePresetsApi = api.injectEndpoints({
|
||||
if (image) {
|
||||
formData.append('image', image);
|
||||
}
|
||||
|
||||
formData.append('name', name);
|
||||
formData.append('positive_prompt', positive_prompt);
|
||||
formData.append('negative_prompt', negative_prompt);
|
||||
formData.append('data', JSON.stringify({ name, positive_prompt, negative_prompt }));
|
||||
|
||||
return {
|
||||
url: buildStylePresetsUrl(`i/${id}`),
|
||||
|
Loading…
Reference in New Issue
Block a user