Addressed merge conflicts for adding UI tooltips

This commit is contained in:
hipsterusername 2022-09-23 09:09:48 -04:00 committed by Lincoln Stein
parent b1d1063a25
commit ac51ec4939
6 changed files with 166 additions and 4 deletions

View File

@ -0,0 +1,59 @@
type FeatureHelpInfo = {
text: string;
href: string;
guideImage: string;
};
export enum Feature {
PROMPT,
GALLERY,
OUTPUT,
SEED_AND_VARIATION,
ESRGAN,
FACE_CORRECTION,
IMAGE_TO_IMAGE,
SAMPLER,
}
export const FEATURES: Record<Feature, FeatureHelpInfo> = {
[Feature.PROMPT]: {
text: 'This field will take all prompt text, including both content and stylistic terms. CLI Commands will not work in the prompt.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.GALLERY]: {
text: 'As new invocations are generated, files from the output directory will be displayed here. Generations have additional options to configure new generations.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.OUTPUT]: {
text: 'The Height and Width of generations can be controlled here. If you experience errors, you may be generating an image too large for your system. The seamless option will more often result in repeating patterns in outputs.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.SEED_AND_VARIATION]: {
text: 'Seed values provide an initial set of noise which guide the denoising process. Try a variation with an amount of between 0 and 1 to change the output image for that seed.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.ESRGAN]: {
text: 'The ESRGAN setting can be used to increase the output resolution without requiring a higher width/height in the initial generation.',
href: 'link/to/docs/feature1.html',
guideImage: 'asset/path.gif',
},
[Feature.FACE_CORRECTION]: {
text: 'Using GFPGAN or CodeFormer, Face Correction will attempt to identify faces in outputs, and correct any defects/abnormalities. Higher values will apply a stronger corrective pressure on outputs.',
href: 'link/to/docs/feature2.html',
guideImage: 'asset/path.gif',
},
[Feature.IMAGE_TO_IMAGE]: {
text: 'ImageToImage allows the upload of an initial image, which InvokeAI will use to guide the generation process, along with a prompt. A lower value for this setting will more closely resemble the original image. Values between 0-1 are accepted, and a range of .25-.75 is recommended ',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
[Feature.SAMPLER]: {
text: 'This setting allows for different denoising samplers to be used, as well as the number of denoising steps used, which will change the resulting output.',
href: 'link/to/docs/feature3.html',
guideImage: 'asset/path.gif',
},
};

View File

@ -0,0 +1,22 @@
import { Box, forwardRef, Icon } from '@chakra-ui/react';
import { IconType } from 'react-icons';
import { MdHelp } from 'react-icons/md';
import { Feature } from '../../app/features';
import GuidePopover from './GuidePopover';
type GuideIconProps = {
feature: Feature;
icon?: IconType;
};
const GuideIcon = forwardRef(
({ feature, icon = MdHelp }: GuideIconProps, ref) => (
<GuidePopover feature={feature}>
<Box ref={ref}>
<Icon as={icon} />
</Box>
</GuidePopover>
)
);
export default GuideIcon;

View File

@ -0,0 +1,51 @@
import {
Popover,
PopoverArrow,
PopoverContent,
PopoverTrigger,
PopoverHeader,
Flex,
Box,
} from '@chakra-ui/react';
import { SystemState } from '../../features/system/systemSlice';
import { useAppSelector } from '../../app/store';
import { RootState } from '../../app/store';
import { createSelector } from '@reduxjs/toolkit';
import { ReactElement } from 'react';
import { Feature, FEATURES } from '../../app/features';
type GuideProps = {
children: ReactElement;
feature: Feature;
};
const systemSelector = createSelector(
(state: RootState) => state.system,
(system: SystemState) => system.shouldDisplayGuides
);
const GuidePopover = ({ children, feature }: GuideProps) => {
const shouldDisplayGuides = useAppSelector(systemSelector);
const { text } = FEATURES[feature];
return shouldDisplayGuides ? (
<Popover trigger={'hover'}>
<PopoverTrigger>
<Box>{children}</Box>
</PopoverTrigger>
<PopoverContent
maxWidth="400px"
onClick={(e) => e.preventDefault()}
cursor={'initial'}
>
<PopoverArrow />
<Flex alignItems={'center'} gap={2} p={4}>
{text}
</Flex>
</PopoverContent>
</Popover>
) : (
<></>
);
};
export default GuidePopover;

View File

@ -31,6 +31,9 @@ import OutputOptions from './OutputOptions';
import ImageToImageOptions from './ImageToImageOptions';
import { ChangeEvent } from 'react';
import GuideIcon from '../../common/components/GuideIcon';
import { Feature } from '../../app/features';
const optionsSelector = createSelector(
(state: RootState) => state.options,
(options: OptionsState) => {
@ -108,6 +111,7 @@ const OptionsAccordion = () => {
<Box flex="1" textAlign="left">
Seed & Variation
</Box>
<GuideIcon feature={Feature.SEED_AND_VARIATION} />
<AccordionIcon />
</AccordionButton>
</h2>
@ -121,6 +125,7 @@ const OptionsAccordion = () => {
<Box flex="1" textAlign="left">
Sampler
</Box>
<GuideIcon feature={Feature.SAMPLER} />
<AccordionIcon />
</AccordionButton>
</h2>
@ -144,6 +149,7 @@ const OptionsAccordion = () => {
onChange={handleChangeShouldRunESRGAN}
/>
</Flex>
<GuideIcon feature={Feature.ESRGAN} />
<AccordionIcon />
</AccordionButton>
</h2>
@ -160,13 +166,14 @@ const OptionsAccordion = () => {
width={'100%'}
mr={2}
>
<Text>Fix Faces (GFPGAN)</Text>
<Text>Face Correction</Text>
<Switch
isDisabled={!isGFPGANAvailable}
isChecked={shouldRunGFPGAN}
onChange={handleChangeShouldRunGFPGAN}
/>
</Flex>
<GuideIcon feature={Feature.FACE_CORRECTION} />
<AccordionIcon />
</AccordionButton>
</h2>
@ -190,6 +197,7 @@ const OptionsAccordion = () => {
onChange={handleChangeShouldUseInitImage}
/>
</Flex>
<GuideIcon feature={Feature.IMAGE_TO_IMAGE} />
<AccordionIcon />
</AccordionButton>
</h2>
@ -203,6 +211,7 @@ const OptionsAccordion = () => {
<Box flex="1" textAlign="left">
Output
</Box>
<GuideIcon feature={Feature.OUTPUT} />
<AccordionIcon />
</AccordionButton>
</h2>

View File

@ -20,6 +20,7 @@ import { useAppDispatch, useAppSelector } from '../../app/store';
import {
setShouldConfirmOnDelete,
setShouldDisplayInProgress,
setShouldDisplayGuides,
SystemState,
} from './systemSlice';
import { RootState } from '../../app/store';
@ -31,8 +32,8 @@ import { cloneElement, ReactElement } from 'react';
const systemSelector = createSelector(
(state: RootState) => state.system,
(system: SystemState) => {
const { shouldDisplayInProgress, shouldConfirmOnDelete } = system;
return { shouldDisplayInProgress, shouldConfirmOnDelete };
const { shouldDisplayInProgress, shouldConfirmOnDelete, shouldDisplayGuides } = system;
return { shouldDisplayInProgress, shouldConfirmOnDelete, shouldDisplayGuides };
},
{
memoizeOptions: { resultEqualityCheck: isEqual },
@ -63,7 +64,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
onClose: onRefreshModalClose,
} = useDisclosure();
const { shouldDisplayInProgress, shouldConfirmOnDelete } =
const { shouldDisplayInProgress, shouldConfirmOnDelete, shouldDisplayGuides } =
useAppSelector(systemSelector);
const dispatch = useAppDispatch();
@ -116,6 +117,19 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
/>
</HStack>
</FormControl>
<FormControl>
<HStack>
<FormLabel marginBottom={1}>
Display help guides in configuration menus
</FormLabel>
<Switch
isChecked={shouldDisplayGuides}
onChange={(e) =>
dispatch(setShouldDisplayGuides(e.target.checked))
}
/>
</HStack>
</FormControl>
<Heading size={'md'}>Reset Web UI</Heading>
<Text>

View File

@ -31,6 +31,8 @@ export interface SystemState extends InvokeAI.SystemStatus, InvokeAI.SystemConfi
totalIterations: number;
currentStatus: string;
currentStatusHasSteps: boolean;
shouldDisplayGuides: boolean;
}
const initialSystemState = {
@ -39,6 +41,7 @@ const initialSystemState = {
log: [],
shouldShowLogViewer: false,
shouldDisplayInProgress: false,
shouldDisplayGuides: true,
isGFPGANAvailable: true,
isESRGANAvailable: true,
socketId: '',
@ -117,6 +120,9 @@ export const systemSlice = createSlice({
setSystemConfig: (state, action: PayloadAction<InvokeAI.SystemConfig>) => {
return { ...state, ...action.payload };
},
setShouldDisplayGuides: (state, action: PayloadAction<boolean>) => {
state.shouldDisplayGuides = action.payload;
},
},
});
@ -132,6 +138,7 @@ export const {
setSystemStatus,
setCurrentStatus,
setSystemConfig,
setShouldDisplayGuides,
} = systemSlice.actions;
export default systemSlice.reducer;