Skip to content

Commit 7ad1c29

Browse files
feat(ui): add actions for reset canvas layers / generation settings to session menus
1 parent fbc629f commit 7ad1c29

File tree

5 files changed

+68
-49
lines changed

5 files changed

+68
-49
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,8 @@
17871787
"newGallerySessionDesc": "This will clear the canvas and all settings except for your model selection. Generations will be sent to the gallery.",
17881788
"newCanvasSession": "New Canvas Session",
17891789
"newCanvasSessionDesc": "This will clear the canvas and all settings except for your model selection. Generations will be staged on the canvas.",
1790+
"resetCanvasLayers": "Reset Canvas Layers",
1791+
"resetGenerationSettings": "Reset Generation Settings",
17901792
"replaceCurrent": "Replace Current",
17911793
"controlLayerEmptyState": "<UploadButton>Upload an image</UploadButton>, drag an image from the <GalleryButton>gallery</GalleryButton> onto this layer, or draw on the canvas to get started.",
17921794
"controlMode": {
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { MenuItem } from '@invoke-ai/ui-library';
2+
import { useAppDispatch } from 'app/store/storeHooks';
3+
import {
4+
useNewCanvasSession,
5+
useNewGallerySession,
6+
} from 'features/controlLayers/components/NewSessionConfirmationAlertDialog';
7+
import { canvasReset } from 'features/controlLayers/store/actions';
8+
import { paramsReset } from 'features/controlLayers/store/paramsSlice';
9+
import { memo, useCallback } from 'react';
10+
import { useTranslation } from 'react-i18next';
11+
import { PiArrowsCounterClockwiseBold, PiFilePlusBold } from 'react-icons/pi';
12+
13+
export const SessionMenuItems = memo(() => {
14+
const { t } = useTranslation();
15+
const dispatch = useAppDispatch();
16+
const { newGallerySessionWithDialog } = useNewGallerySession();
17+
const { newCanvasSessionWithDialog } = useNewCanvasSession();
18+
const resetCanvasLayers = useCallback(() => {
19+
dispatch(canvasReset());
20+
}, [dispatch]);
21+
const resetGenerationSettings = useCallback(() => {
22+
dispatch(paramsReset());
23+
}, [dispatch]);
24+
return (
25+
<>
26+
<MenuItem icon={<PiFilePlusBold />} onClick={newGallerySessionWithDialog}>
27+
{t('controlLayers.newGallerySession')}
28+
</MenuItem>
29+
<MenuItem icon={<PiFilePlusBold />} onClick={newCanvasSessionWithDialog}>
30+
{t('controlLayers.newCanvasSession')}
31+
</MenuItem>
32+
<MenuItem icon={<PiArrowsCounterClockwiseBold />} onClick={resetCanvasLayers}>
33+
{t('controlLayers.resetCanvasLayers')}
34+
</MenuItem>
35+
<MenuItem icon={<PiArrowsCounterClockwiseBold />} onClick={resetGenerationSettings}>
36+
{t('controlLayers.resetGenerationSettings')}
37+
</MenuItem>
38+
</>
39+
);
40+
});
41+
42+
SessionMenuItems.displayName = 'SessionMenuItems';

invokeai/frontend/web/src/features/controlLayers/components/Toolbar/CanvasToolbarNewSessionMenuButton.tsx

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
import { IconButton, Menu, MenuButton, MenuItem, MenuList } from '@invoke-ai/ui-library';
2-
import {
3-
useNewCanvasSession,
4-
useNewGallerySession,
5-
} from 'features/controlLayers/components/NewSessionConfirmationAlertDialog';
1+
import { IconButton, Menu, MenuButton, MenuList } from '@invoke-ai/ui-library';
2+
import { SessionMenuItems } from 'common/components/SessionMenuItems';
63
import { memo } from 'react';
74
import { useTranslation } from 'react-i18next';
8-
import { PiFilePlusBold, PiImageBold, PiPaintBrushBold } from 'react-icons/pi';
5+
import { PiFilePlusBold } from 'react-icons/pi';
96

107
export const CanvasToolbarNewSessionMenuButton = memo(() => {
118
const { t } = useTranslation();
12-
const { newGallerySessionWithDialog } = useNewGallerySession();
13-
const { newCanvasSessionWithDialog } = useNewCanvasSession();
149
return (
1510
<Menu placement="bottom-end">
1611
<MenuButton
@@ -21,12 +16,7 @@ export const CanvasToolbarNewSessionMenuButton = memo(() => {
2116
alignSelf="stretch"
2217
/>
2318
<MenuList>
24-
<MenuItem icon={<PiImageBold />} onClick={newGallerySessionWithDialog}>
25-
{t('controlLayers.newGallerySession')}
26-
</MenuItem>
27-
<MenuItem icon={<PiPaintBrushBold />} onClick={newCanvasSessionWithDialog}>
28-
{t('controlLayers.newCanvasSession')}
29-
</MenuItem>
19+
<SessionMenuItems />
3020
</MenuList>
3121
</Menu>
3222
);

invokeai/frontend/web/src/features/controlLayers/store/paramsSlice.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,24 +273,27 @@ export const paramsSlice = createSlice({
273273
setCanvasCoherenceMinDenoise: (state, action: PayloadAction<number>) => {
274274
state.canvasCoherenceMinDenoise = action.payload;
275275
},
276+
paramsReset: (state) => resetState(state),
276277
},
277278
extraReducers(builder) {
278-
builder.addMatcher(newSessionRequested, (state) => {
279-
// When a new session is requested, we need to keep the current model selections, plus dependent state
280-
// like VAE precision. Everything else gets reset to default.
281-
const newState = deepClone(initialState);
282-
newState.model = state.model;
283-
newState.vae = state.vae;
284-
newState.fluxVAE = state.fluxVAE;
285-
newState.vaePrecision = state.vaePrecision;
286-
newState.t5EncoderModel = state.t5EncoderModel;
287-
newState.clipEmbedModel = state.clipEmbedModel;
288-
newState.refinerModel = state.refinerModel;
289-
return newState;
290-
});
279+
builder.addMatcher(newSessionRequested, (state) => resetState(state));
291280
},
292281
});
293282

283+
const resetState = (state: ParamsState): ParamsState => {
284+
// When a new session is requested, we need to keep the current model selections, plus dependent state
285+
// like VAE precision. Everything else gets reset to default.
286+
const newState = deepClone(initialState);
287+
newState.model = state.model;
288+
newState.vae = state.vae;
289+
newState.fluxVAE = state.fluxVAE;
290+
newState.vaePrecision = state.vaePrecision;
291+
newState.t5EncoderModel = state.t5EncoderModel;
292+
newState.clipEmbedModel = state.clipEmbedModel;
293+
newState.refinerModel = state.refinerModel;
294+
return newState;
295+
};
296+
294297
export const {
295298
setInfillMethod,
296299
setInfillTileSize,
@@ -334,6 +337,7 @@ export const {
334337
setRefinerNegativeAestheticScore,
335338
setRefinerStart,
336339
modelChanged,
340+
paramsReset,
337341
} = paramsSlice.actions;
338342

339343
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */

invokeai/frontend/web/src/features/queue/components/QueueActionsMenuButton.tsx

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { IconButton, Menu, MenuButton, MenuGroup, MenuItem, MenuList } from '@invoke-ai/ui-library';
22
import { useAppDispatch } from 'app/store/storeHooks';
3-
import {
4-
useNewCanvasSession,
5-
useNewGallerySession,
6-
} from 'features/controlLayers/components/NewSessionConfirmationAlertDialog';
3+
import { SessionMenuItems } from 'common/components/SessionMenuItems';
74
import { useClearQueue } from 'features/queue/components/ClearQueueConfirmationAlertDialog';
85
import { QueueCountBadge } from 'features/queue/components/QueueCountBadge';
96
import { usePauseProcessor } from 'features/queue/hooks/usePauseProcessor';
@@ -12,25 +9,14 @@ import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
129
import { setActiveTab } from 'features/ui/store/uiSlice';
1310
import { memo, useCallback, useRef } from 'react';
1411
import { useTranslation } from 'react-i18next';
15-
import {
16-
PiImageBold,
17-
PiListBold,
18-
PiPaintBrushBold,
19-
PiPauseFill,
20-
PiPlayFill,
21-
PiQueueBold,
22-
PiTrashSimpleBold,
23-
PiXBold,
24-
} from 'react-icons/pi';
12+
import { PiListBold, PiPauseFill, PiPlayFill, PiQueueBold, PiTrashSimpleBold, PiXBold } from 'react-icons/pi';
2513

2614
export const QueueActionsMenuButton = memo(() => {
2715
const ref = useRef<HTMLDivElement>(null);
2816
const dispatch = useAppDispatch();
2917
const { t } = useTranslation();
3018
const isPauseEnabled = useFeatureStatus('pauseQueue');
3119
const isResumeEnabled = useFeatureStatus('resumeQueue');
32-
const { newGallerySessionWithDialog } = useNewGallerySession();
33-
const { newCanvasSessionWithDialog } = useNewCanvasSession();
3420
const clearQueue = useClearQueue();
3521
const {
3622
resumeProcessor,
@@ -52,12 +38,7 @@ export const QueueActionsMenuButton = memo(() => {
5238
<MenuButton ref={ref} as={IconButton} size="lg" aria-label="Queue Actions Menu" icon={<PiListBold />} />
5339
<MenuList>
5440
<MenuGroup title={t('common.new')}>
55-
<MenuItem icon={<PiImageBold />} onClick={newGallerySessionWithDialog}>
56-
{t('controlLayers.newGallerySession')}
57-
</MenuItem>
58-
<MenuItem icon={<PiPaintBrushBold />} onClick={newCanvasSessionWithDialog}>
59-
{t('controlLayers.newCanvasSession')}
60-
</MenuItem>
41+
<SessionMenuItems />
6142
</MenuGroup>
6243
<MenuGroup title={t('queue.queue')}>
6344
<MenuItem

0 commit comments

Comments
 (0)