Skip to content

Commit 77f5e1e

Browse files
Mary HippMary Hipp
authored andcommitted
feat(ui): add out of sync details to model default settings button
1 parent e6ab6e0 commit 77f5e1e

File tree

2 files changed

+150
-6
lines changed

2 files changed

+150
-6
lines changed

invokeai/frontend/web/public/locales/en.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,10 @@
713713
"convertToDiffusersHelpText4": "This is a one time process only. It might take around 30s-60s depending on the specifications of your computer.",
714714
"convertToDiffusersHelpText5": "Please make sure you have enough disk space. Models generally vary between 2GB-7GB in size.",
715715
"convertToDiffusersHelpText6": "Do you wish to convert this model?",
716+
"noDefaultSettings": "No Default Settings configured for this model. Visit the Model Manager to configure.",
716717
"defaultSettings": "Default Settings",
717718
"defaultSettingsSaved": "Default Settings Saved",
719+
"defaultSettingsOutOfSync": "The below generation settings are out of sync for this model's default settings",
718720
"delete": "Delete",
719721
"deleteConfig": "Delete Config",
720722
"deleteModel": "Delete Model",
@@ -773,6 +775,7 @@
773775
"pruneTooltip": "Prune finished imports from queue",
774776
"repo_id": "Repo ID",
775777
"repoVariant": "Repo Variant",
778+
"restoreDefaultSettings": "Click to reset to default settings",
776779
"scanFolder": "Scan Folder",
777780
"scanFolderHelper": "The folder will be recursively scanned for models. This can take a few moments for very large folders.",
778781
"scanPlaceholder": "Path to a local folder",
@@ -799,7 +802,7 @@
799802
"uploadImage": "Upload Image",
800803
"urlOrLocalPath": "URL or Local Path",
801804
"urlOrLocalPathHelper": "URLs should point to a single file. Local paths can point to a single file or folder for a single diffusers model.",
802-
"useDefaultSettings": "Use Default Settings",
805+
"usingDefaultSettings": "Using default settings",
803806
"vae": "VAE",
804807
"vaePrecision": "VAE Precision",
805808
"variant": "Variant",
Lines changed: 146 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,155 @@
1-
import { IconButton } from '@invoke-ai/ui-library';
1+
import { Flex, IconButton, ListItem, Text, UnorderedList } from '@invoke-ai/ui-library';
22
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
3-
import { selectModel } from 'features/controlLayers/store/paramsSlice';
3+
import {
4+
selectCFGRescaleMultiplier,
5+
selectCFGScale,
6+
selectGuidance,
7+
selectModel,
8+
selectScheduler,
9+
selectSteps,
10+
selectVAE,
11+
selectVAEPrecision,
12+
} from 'features/controlLayers/store/paramsSlice';
13+
import { selectHeight, selectWidth } from 'features/controlLayers/store/selectors';
414
import { setDefaultSettings } from 'features/parameters/store/actions';
5-
import { useCallback } from 'react';
15+
import { useCallback, useMemo } from 'react';
616
import { useTranslation } from 'react-i18next';
717
import { PiSparkleFill } from 'react-icons/pi';
18+
import { modelConfigsAdapterSelectors, useGetModelConfigsQuery } from 'services/api/endpoints/models';
19+
import { isNonRefinerMainModelConfig } from 'services/api/types';
820

921
export const UseDefaultSettingsButton = () => {
1022
const model = useAppSelector(selectModel);
1123
const { t } = useTranslation();
1224
const dispatch = useAppDispatch();
25+
const { data: modelConfigs } = useGetModelConfigsQuery();
26+
27+
const scheduler = useAppSelector(selectScheduler);
28+
const steps = useAppSelector(selectSteps);
29+
const vae = useAppSelector(selectVAE);
30+
const vaePrecision = useAppSelector(selectVAEPrecision);
31+
const width = useAppSelector(selectWidth);
32+
const height = useAppSelector(selectHeight);
33+
const guidance = useAppSelector(selectGuidance);
34+
const cfg = useAppSelector(selectCFGScale);
35+
const cfgRescale = useAppSelector(selectCFGRescaleMultiplier);
36+
37+
const modelConfig = useMemo(() => {
38+
if (!modelConfigs) {
39+
return null;
40+
}
41+
if (model === null) {
42+
return null;
43+
}
44+
45+
return modelConfigsAdapterSelectors.selectById(modelConfigs, model.key);
46+
}, [modelConfigs, model]);
47+
48+
const hasDefaultSettings = useMemo(() => {
49+
const settings = modelConfig && isNonRefinerMainModelConfig(modelConfig) && modelConfig.default_settings;
50+
return settings && Object.values(settings).some((setting) => !!setting);
51+
}, [modelConfig]);
52+
53+
const defaultSettings = useMemo(() => {
54+
return modelConfig && isNonRefinerMainModelConfig(modelConfig) && modelConfig.default_settings
55+
? modelConfig.default_settings
56+
: {};
57+
}, [modelConfig]);
58+
59+
const outOfSyncSettings = useMemo(() => {
60+
const settings = [];
61+
if (hasDefaultSettings) {
62+
const {
63+
vae: defaultVAE,
64+
vae_precision: defaultVAEPrecision,
65+
cfg_scale: defaultCfg,
66+
cfg_rescale_multiplier: defaultCfgRescale,
67+
steps: defaultSteps,
68+
scheduler: defaultScheduler,
69+
width: defaultWidth,
70+
height: defaultHeight,
71+
guidance: defaultGuidance,
72+
} = defaultSettings;
73+
74+
if (defaultVAE && vae && defaultVAE !== vae.key) {
75+
settings.push(t('modelManager.vae'));
76+
}
77+
78+
if (defaultVAE && !vae && defaultVAE !== 'default') {
79+
settings.push(t('modelManager.vae'));
80+
}
81+
82+
if (defaultVAEPrecision && defaultVAEPrecision !== vaePrecision) {
83+
settings.push(t('modelManager.vaePrecision'));
84+
}
85+
86+
if (defaultCfg && defaultCfg !== cfg) {
87+
settings.push(t('parameters.cfgScale'));
88+
}
89+
90+
if (defaultCfgRescale && defaultCfgRescale !== cfgRescale) {
91+
settings.push(t('parameters.cfgRescaleMultiplier'));
92+
}
93+
94+
if (defaultSteps && defaultSteps !== steps) {
95+
settings.push(t('parameters.steps'));
96+
}
97+
98+
if (defaultScheduler && defaultScheduler !== scheduler) {
99+
settings.push(t('parameters.scheduler'));
100+
}
101+
102+
if (defaultWidth && defaultWidth !== width) {
103+
settings.push(t('parameters.width'));
104+
}
105+
106+
if (defaultHeight && defaultHeight !== height) {
107+
settings.push(t('parameters.height'));
108+
}
109+
110+
if (defaultGuidance && defaultGuidance !== guidance) {
111+
settings.push(t('parameters.guidance'));
112+
}
113+
}
114+
return settings;
115+
}, [
116+
hasDefaultSettings,
117+
vae,
118+
vaePrecision,
119+
cfg,
120+
cfgRescale,
121+
steps,
122+
scheduler,
123+
width,
124+
height,
125+
guidance,
126+
t,
127+
defaultSettings,
128+
]);
129+
130+
const tooltip = useMemo(() => {
131+
if (!hasDefaultSettings) {
132+
return t('modelManager.noDefaultSettings');
133+
}
134+
135+
if (outOfSyncSettings.length === 0) {
136+
return t('modelManager.usingDefaultSettings');
137+
}
138+
139+
return (
140+
<Flex direction="column" gap={3}>
141+
<Flex direction="column">
142+
<Text>{t('modelManager.defaultSettingsOutOfSync')}</Text>
143+
<UnorderedList>
144+
{outOfSyncSettings.map((setting) => (
145+
<ListItem key={setting}>{setting}</ListItem>
146+
))}
147+
</UnorderedList>
148+
</Flex>
149+
<Text>{t('modelManager.restoreDefaultSettings')}</Text>
150+
</Flex>
151+
);
152+
}, [outOfSyncSettings, t, hasDefaultSettings]);
13153

14154
const handleClickDefaultSettings = useCallback(() => {
15155
dispatch(setDefaultSettings());
@@ -18,12 +158,13 @@ export const UseDefaultSettingsButton = () => {
18158
return (
19159
<IconButton
20160
icon={<PiSparkleFill />}
21-
tooltip={t('modelManager.useDefaultSettings')}
161+
tooltip={tooltip}
22162
aria-label={t('modelManager.useDefaultSettings')}
23-
isDisabled={!model}
163+
isDisabled={!model || !hasDefaultSettings}
24164
onClick={handleClickDefaultSettings}
25165
size="sm"
26166
variant="ghost"
167+
colorScheme={outOfSyncSettings.length ? 'warning' : 'invokeBlue'}
27168
/>
28169
);
29170
};

0 commit comments

Comments
 (0)