Skip to content

Commit 4405c39

Browse files
[3.1] UI Fixes (#4376)
## What type of PR is this? (check all applicable) - [x] Feature - [x] Bug Fix ## Have you discussed this change with the InvokeAI team? - [x] Yes ## Description - Keep Boards Modal open by default. - Combine Coherence and Mask settings under Compositing - Auto Change Dimensions based on model type (option) - Size resets are now model dependent - Add Set Control Image Height & Width to Width and Height option. - Fix numerous color & spacing issues (especially those pertaining to sliders being too close to the bottom) - Add Lock Ratio Option
2 parents 600e9ec + 1d6be7f commit 4405c39

File tree

34 files changed

+467
-182
lines changed

34 files changed

+467
-182
lines changed

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,12 +506,13 @@
506506
"hiresStrength": "High Res Strength",
507507
"imageFit": "Fit Initial Image To Output Size",
508508
"codeformerFidelity": "Fidelity",
509+
"compositingSettingsHeader": "Compositing Settings",
509510
"maskAdjustmentsHeader": "Mask Adjustments",
510-
"maskBlur": "Mask Blur",
511-
"maskBlurMethod": "Mask Blur Method",
511+
"maskBlur": "Blur",
512+
"maskBlurMethod": "Blur Method",
512513
"coherencePassHeader": "Coherence Pass",
513-
"coherenceSteps": "Coherence Pass Steps",
514-
"coherenceStrength": "Coherence Pass Strength",
514+
"coherenceSteps": "Steps",
515+
"coherenceStrength": "Strength",
515516
"seamLowThreshold": "Low",
516517
"seamHighThreshold": "High",
517518
"scaleBeforeProcessing": "Scale Before Processing",
@@ -569,6 +570,7 @@
569570
"useSlidersForAll": "Use Sliders For All Options",
570571
"showProgressInViewer": "Show Progress Images in Viewer",
571572
"antialiasProgressImages": "Antialias Progress Images",
573+
"autoChangeDimensions": "Update W/H To Model Defaults On Change",
572574
"resetWebUI": "Reset Web UI",
573575
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
574576
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
@@ -712,7 +714,8 @@
712714
"ui": {
713715
"showProgressImages": "Show Progress Images",
714716
"hideProgressImages": "Hide Progress Images",
715-
"swapSizes": "Swap Sizes"
717+
"swapSizes": "Swap Sizes",
718+
"lockRatio": "Lock Ratio"
716719
},
717720
"nodes": {
718721
"reloadNodeTemplates": "Reload Node Templates",

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { logger } from 'app/logging/logger';
2+
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
23
import { controlNetRemoved } from 'features/controlNet/store/controlNetSlice';
34
import { loraRemoved } from 'features/lora/store/loraSlice';
45
import { modelSelected } from 'features/parameters/store/actions';
56
import {
67
modelChanged,
8+
setHeight,
9+
setWidth,
710
vaeSelected,
811
} from 'features/parameters/store/generationSlice';
912
import { zMainOrOnnxModel } from 'features/parameters/types/parameterSchemas';
@@ -74,6 +77,22 @@ export const addModelSelectedListener = () => {
7477
}
7578
}
7679

80+
// Update Width / Height / Bounding Box Dimensions on Model Change
81+
if (
82+
state.generation.model?.base_model !== newModel.base_model &&
83+
state.ui.shouldAutoChangeDimensions
84+
) {
85+
if (['sdxl', 'sdxl-refiner'].includes(newModel.base_model)) {
86+
dispatch(setWidth(1024));
87+
dispatch(setHeight(1024));
88+
dispatch(setBoundingBoxDimensions({ width: 1024, height: 1024 }));
89+
} else {
90+
dispatch(setWidth(512));
91+
dispatch(setHeight(512));
92+
dispatch(setBoundingBoxDimensions({ width: 512, height: 512 }));
93+
}
94+
}
95+
7796
dispatch(modelChanged(newModel));
7897
},
7998
});

invokeai/frontend/web/src/app/store/store.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import {
66
configureStore,
77
} from '@reduxjs/toolkit';
88
import canvasReducer from 'features/canvas/store/canvasSlice';
9+
import changeBoardModalReducer from 'features/changeBoardModal/store/slice';
910
import controlNetReducer from 'features/controlNet/store/controlNetSlice';
11+
import deleteImageModalReducer from 'features/deleteImageModal/store/slice';
1012
import dynamicPromptsReducer from 'features/dynamicPrompts/store/dynamicPromptsSlice';
1113
import galleryReducer from 'features/gallery/store/gallerySlice';
12-
import deleteImageModalReducer from 'features/deleteImageModal/store/slice';
13-
import changeBoardModalReducer from 'features/changeBoardModal/store/slice';
1414
import loraReducer from 'features/lora/store/loraSlice';
1515
import nodesReducer from 'features/nodes/store/nodesSlice';
1616
import generationReducer from 'features/parameters/store/generationSlice';

invokeai/frontend/web/src/common/components/IAICollapse.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ const IAICollapse = (props: IAIToggleCollapseProps) => {
8686
<Collapse in={isOpen} animateOpacity style={{ overflow: 'unset' }}>
8787
<Box
8888
sx={{
89-
p: 2,
90-
pt: 3,
89+
p: 4,
90+
pb: 4,
9191
borderBottomRadius: 'base',
9292
bg: 'base.150',
9393
_dark: {

invokeai/frontend/web/src/features/controlNet/components/ControlNetImagePreview.tsx

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@ import { stateSelector } from 'app/store/store';
55
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
66
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
77
import IAIDndImage from 'common/components/IAIDndImage';
8+
import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
89
import {
910
TypesafeDraggableData,
1011
TypesafeDroppableData,
1112
} from 'features/dnd/types';
13+
import { setHeight, setWidth } from 'features/parameters/store/generationSlice';
14+
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
1215
import { memo, useCallback, useMemo, useState } from 'react';
13-
import { FaSave, FaUndo } from 'react-icons/fa';
16+
import { FaRulerVertical, FaSave, FaUndo } from 'react-icons/fa';
1417
import {
1518
useAddImageToBoardMutation,
1619
useChangeImageIsIntermediateMutation,
1720
useGetImageDTOQuery,
21+
useRemoveImageFromBoardMutation,
1822
} from 'services/api/endpoints/images';
1923
import { PostUploadAction } from 'services/api/types';
2024
import IAIDndImageIcon from '../../../common/components/IAIDndImageIcon';
@@ -54,6 +58,7 @@ const ControlNetImagePreview = ({ isSmall, controlNet }: Props) => {
5458
const dispatch = useAppDispatch();
5559

5660
const { pendingControlImages, autoAddBoardId } = useAppSelector(selector);
61+
const activeTabName = useAppSelector(activeTabNameSelector);
5762

5863
const [isMouseOverImage, setIsMouseOverImage] = useState(false);
5964

@@ -67,23 +72,54 @@ const ControlNetImagePreview = ({ isSmall, controlNet }: Props) => {
6772

6873
const [changeIsIntermediate] = useChangeImageIsIntermediateMutation();
6974
const [addToBoard] = useAddImageToBoardMutation();
70-
75+
const [removeFromBoard] = useRemoveImageFromBoardMutation();
7176
const handleResetControlImage = useCallback(() => {
7277
dispatch(controlNetImageChanged({ controlNetId, controlImage: null }));
7378
}, [controlNetId, dispatch]);
7479

75-
const handleSaveControlImage = useCallback(() => {
80+
const handleSaveControlImage = useCallback(async () => {
7681
if (!processedControlImage) {
7782
return;
7883
}
7984

80-
changeIsIntermediate({
85+
await changeIsIntermediate({
8186
imageDTO: processedControlImage,
8287
is_intermediate: false,
83-
});
88+
}).unwrap();
89+
90+
if (autoAddBoardId !== 'none') {
91+
addToBoard({
92+
imageDTO: processedControlImage,
93+
board_id: autoAddBoardId,
94+
});
95+
} else {
96+
removeFromBoard({ imageDTO: processedControlImage });
97+
}
98+
}, [
99+
processedControlImage,
100+
changeIsIntermediate,
101+
autoAddBoardId,
102+
addToBoard,
103+
removeFromBoard,
104+
]);
105+
106+
const handleSetControlImageToDimensions = useCallback(() => {
107+
if (!processedControlImage) {
108+
return;
109+
}
84110

85-
addToBoard({ imageDTO: processedControlImage, board_id: autoAddBoardId });
86-
}, [processedControlImage, autoAddBoardId, changeIsIntermediate, addToBoard]);
111+
if (activeTabName === 'unifiedCanvas') {
112+
dispatch(
113+
setBoundingBoxDimensions({
114+
width: processedControlImage.width,
115+
height: processedControlImage.height,
116+
})
117+
);
118+
} else {
119+
dispatch(setWidth(processedControlImage.width));
120+
dispatch(setHeight(processedControlImage.height));
121+
}
122+
}, [processedControlImage, activeTabName, dispatch]);
87123

88124
const handleMouseEnter = useCallback(() => {
89125
setIsMouseOverImage(true);
@@ -144,21 +180,7 @@ const ControlNetImagePreview = ({ isSmall, controlNet }: Props) => {
144180
imageDTO={controlImage}
145181
isDropDisabled={shouldShowProcessedImage || !isEnabled}
146182
postUploadAction={postUploadAction}
147-
>
148-
<>
149-
<IAIDndImageIcon
150-
onClick={handleResetControlImage}
151-
icon={controlImage ? <FaUndo /> : undefined}
152-
tooltip="Reset Control Image"
153-
/>
154-
<IAIDndImageIcon
155-
onClick={handleSaveControlImage}
156-
icon={controlImage ? <FaSave size={16} /> : undefined}
157-
tooltip="Save Control Image"
158-
styleOverrides={{ marginTop: 6 }}
159-
/>
160-
</>
161-
</IAIDndImage>
183+
/>
162184

163185
<Box
164186
sx={{
@@ -179,22 +201,29 @@ const ControlNetImagePreview = ({ isSmall, controlNet }: Props) => {
179201
imageDTO={processedControlImage}
180202
isUploadDisabled={true}
181203
isDropDisabled={!isEnabled}
182-
>
183-
<>
184-
<IAIDndImageIcon
185-
onClick={handleResetControlImage}
186-
icon={controlImage ? <FaUndo /> : undefined}
187-
tooltip="Reset Control Image"
188-
/>
189-
<IAIDndImageIcon
190-
onClick={handleSaveControlImage}
191-
icon={controlImage ? <FaSave size={16} /> : undefined}
192-
tooltip="Save Control Image"
193-
styleOverrides={{ marginTop: 6 }}
194-
/>
195-
</>
196-
</IAIDndImage>
204+
/>
197205
</Box>
206+
207+
<>
208+
<IAIDndImageIcon
209+
onClick={handleResetControlImage}
210+
icon={controlImage ? <FaUndo /> : undefined}
211+
tooltip="Reset Control Image"
212+
/>
213+
<IAIDndImageIcon
214+
onClick={handleSaveControlImage}
215+
icon={controlImage ? <FaSave size={16} /> : undefined}
216+
tooltip="Save Control Image"
217+
styleOverrides={{ marginTop: 6 }}
218+
/>
219+
<IAIDndImageIcon
220+
onClick={handleSetControlImageToDimensions}
221+
icon={controlImage ? <FaRulerVertical size={16} /> : undefined}
222+
tooltip="Set Control Image Dimensions To W/H"
223+
styleOverrides={{ marginTop: 12 }}
224+
/>
225+
</>
226+
198227
{pendingControlImages.includes(controlNetId) && (
199228
<Flex
200229
sx={{

invokeai/frontend/web/src/features/dynamicPrompts/components/ParamDynamicPromptsCollapse.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { stateSelector } from 'app/store/store';
44
import { useAppSelector } from 'app/store/storeHooks';
55
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
66
import IAICollapse from 'common/components/IAICollapse';
7+
import { memo } from 'react';
8+
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
79
import ParamDynamicPromptsCombinatorial from './ParamDynamicPromptsCombinatorial';
810
import ParamDynamicPromptsToggle from './ParamDynamicPromptsEnabled';
911
import ParamDynamicPromptsMaxPrompts from './ParamDynamicPromptsMaxPrompts';
10-
import { useFeatureStatus } from '../../system/hooks/useFeatureStatus';
11-
import { memo } from 'react';
1212

1313
const selector = createSelector(
1414
stateSelector,

invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const ImageGalleryContent = () => {
3939
const { galleryView } = useAppSelector(selector);
4040
const dispatch = useAppDispatch();
4141
const { isOpen: isBoardListOpen, onToggle: onToggleBoardList } =
42-
useDisclosure();
42+
useDisclosure({ defaultIsOpen: true });
4343

4444
const handleClickImages = useCallback(() => {
4545
dispatch(galleryViewChanged('images'));

invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/BoundingBox/ParamBoundingBoxHeight.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ const selector = createSelector(
1414
[stateSelector, isStagingSelector],
1515
({ canvas, generation }, isStaging) => {
1616
const { boundingBoxDimensions } = canvas;
17-
const { aspectRatio } = generation;
17+
const { model, aspectRatio } = generation;
1818
return {
19+
model,
1920
boundingBoxDimensions,
2021
isStaging,
2122
aspectRatio,
@@ -26,11 +27,15 @@ const selector = createSelector(
2627

2728
const ParamBoundingBoxWidth = () => {
2829
const dispatch = useAppDispatch();
29-
const { boundingBoxDimensions, isStaging, aspectRatio } =
30+
const { model, boundingBoxDimensions, isStaging, aspectRatio } =
3031
useAppSelector(selector);
3132

3233
const { t } = useTranslation();
3334

35+
const initial = ['sdxl', 'sdxl-refiner'].includes(model?.base_model as string)
36+
? 1024
37+
: 512;
38+
3439
const handleChangeHeight = (v: number) => {
3540
dispatch(
3641
setBoundingBoxDimensions({
@@ -53,15 +58,15 @@ const ParamBoundingBoxWidth = () => {
5358
dispatch(
5459
setBoundingBoxDimensions({
5560
...boundingBoxDimensions,
56-
height: Math.floor(512),
61+
height: Math.floor(initial),
5762
})
5863
);
5964
if (aspectRatio) {
60-
const newWidth = roundToMultiple(512 * aspectRatio, 64);
65+
const newWidth = roundToMultiple(initial * aspectRatio, 64);
6166
dispatch(
6267
setBoundingBoxDimensions({
6368
width: newWidth,
64-
height: Math.floor(512),
69+
height: Math.floor(initial),
6570
})
6671
);
6772
}
@@ -71,7 +76,7 @@ const ParamBoundingBoxWidth = () => {
7176
<IAISlider
7277
label={t('parameters.boundingBoxHeight')}
7378
min={64}
74-
max={1024}
79+
max={1536}
7580
step={64}
7681
value={boundingBoxDimensions.height}
7782
onChange={handleChangeHeight}

0 commit comments

Comments
 (0)