Skip to content

Commit 463b105

Browse files
author
Attila Cseh
committed
paramsSlice refactored
1 parent aa58b4c commit 463b105

File tree

101 files changed

+1018
-659
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+1018
-659
lines changed

invokeai/frontend/web/.storybook/ReduxInit.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@ import type { PropsWithChildren } from 'react';
33
import { memo, useEffect } from 'react';
44

55
import { useAppDispatch } from '../src/app/store/storeHooks';
6-
import { modelChanged } from '../src/features/controlLayers/store/paramsSlice';
6+
import { modelChanged } from 'features/controlLayers/store/actions';
7+
import { useParamsDispatch } from 'features/controlLayers/store/paramsSlice';
78
/**
89
* Initializes some state for storybook. Must be in a different component
910
* so that it is run inside the redux context.
1011
*/
1112
export const ReduxInit = memo(({ children }: PropsWithChildren) => {
12-
const dispatch = useAppDispatch();
13+
const dispatch = useParamsDispatch();
1314
useGlobalModifiersInit();
1415
useEffect(() => {
15-
dispatch(
16-
modelChanged({ model: { key: 'test_model', hash: 'some_hash', name: 'some name', base: 'sd-1', type: 'main' } })
17-
);
16+
dispatch(modelChanged, {
17+
model: { key: 'test_model', hash: 'some_hash', name: 'some name', base: 'sd-1', type: 'main' },
18+
});
1819
}, [dispatch]);
1920

2021
return children;

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import type { AppStartListening } from 'app/store/store';
2-
import { setInfillMethod } from 'features/controlLayers/store/paramsSlice';
2+
import { paramsDispatch, selectActiveParams, setInfillMethod } from 'features/controlLayers/store/paramsSlice';
33
import { shouldUseNSFWCheckerChanged, shouldUseWatermarkerChanged } from 'features/system/store/systemSlice';
44
import { appInfoApi } from 'services/api/endpoints/appInfo';
55

66
export const addAppConfigReceivedListener = (startAppListening: AppStartListening) => {
77
startAppListening({
88
matcher: appInfoApi.endpoints.getAppConfig.matchFulfilled,
9-
effect: (action, { getState, dispatch }) => {
9+
effect: (action, api) => {
10+
const { getState, dispatch } = api;
1011
const { infill_methods = [], nsfw_methods = [], watermarking_methods = [] } = action.payload;
11-
const infillMethod = getState().params.infillMethod;
12+
const infillMethod = selectActiveParams(getState()).infillMethod;
1213

1314
if (!infill_methods.includes(infillMethod)) {
1415
// If the selected infill method does not exist, prefer 'lama' if it's in the list, otherwise 'tile'.
1516
// TODO(psyche): lama _should_ always be in the list, but the API doesn't guarantee it...
1617
const infillMethod = infill_methods.includes('lama') ? 'lama' : 'tile';
17-
dispatch(setInfillMethod(infillMethod));
18+
paramsDispatch(api, setInfillMethod, infillMethod);
1819
}
1920

2021
if (!nsfw_methods.includes('nsfw_checker')) {

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { logger } from 'app/logging/logger';
22
import type { AppStartListening } from 'app/store/store';
3+
import { modelChanged } from 'features/controlLayers/store/actions';
34
import { bboxSyncedToOptimalDimension, rgRefImageModelChanged } from 'features/controlLayers/store/canvasSlice';
45
import {
56
buildSelectIsStagingBySessionId,
67
selectActiveCanvasSessionId,
78
} from 'features/controlLayers/store/canvasStagingAreaSlice';
89
import { loraIsEnabledChanged } from 'features/controlLayers/store/lorasSlice';
9-
import { modelChanged, syncedToOptimalDimension, vaeSelected } from 'features/controlLayers/store/paramsSlice';
10+
import {
11+
paramsDispatch,
12+
selectActiveParams,
13+
syncedToOptimalDimension,
14+
vaeSelected,
15+
} from 'features/controlLayers/store/paramsSlice';
1016
import { refImageModelChanged, selectReferenceImageEntities } from 'features/controlLayers/store/refImagesSlice';
1117
import {
1218
selectActiveCanvas,
@@ -34,7 +40,8 @@ const log = logger('models');
3440
export const addModelSelectedListener = (startAppListening: AppStartListening) => {
3541
startAppListening({
3642
actionCreator: modelSelected,
37-
effect: (action, { getState, dispatch }) => {
43+
effect: (action, api) => {
44+
const { getState, dispatch } = api;
3845
const state = getState();
3946
const result = zParameterModel.safeParse(action.payload);
4047

@@ -45,7 +52,8 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) =
4552

4653
const newModel = result.data;
4754
const newBase = newModel.base;
48-
const didBaseModelChange = state.params.model?.base !== newBase;
55+
const params = selectActiveParams(state);
56+
const didBaseModelChange = params.model?.base !== newBase;
4957

5058
if (didBaseModelChange) {
5159
// we may need to reset some incompatible submodels
@@ -60,9 +68,9 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) =
6068
});
6169

6270
// handle incompatible vae
63-
const { vae } = state.params;
71+
const { vae } = params;
6472
if (vae && vae.base !== newBase) {
65-
dispatch(vaeSelected(null));
73+
paramsDispatch(api, vaeSelected, null);
6674
modelsUpdatedDisabledOrCleared += 1;
6775
}
6876

@@ -155,13 +163,13 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) =
155163
}
156164
}
157165

158-
dispatch(modelChanged({ model: newModel, previousModel: state.params.model }));
166+
paramsDispatch(api, modelChanged, { model: newModel, previousModel: params.model });
159167

160168
const modelBase = selectBboxModelBase(state);
161169

162-
if (modelBase !== state.params.model?.base) {
170+
if (modelBase !== params.model?.base) {
163171
// Sync generate tab settings whenever the model base changes
164-
dispatch(syncedToOptimalDimension());
172+
paramsDispatch(api, syncedToOptimalDimension);
165173
const sessionId = selectActiveCanvasSessionId(state);
166174
const selectIsStaging = buildSelectIsStagingBySessionId(sessionId);
167175
const isStaging = selectIsStaging(state);

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

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { logger } from 'app/logging/logger';
22
import type { AppDispatch, AppStartListening, RootState } from 'app/store/store';
3+
import { modelChanged } from 'features/controlLayers/store/actions';
34
import { controlLayerModelChanged, rgRefImageModelChanged } from 'features/controlLayers/store/canvasSlice';
45
import { loraDeleted } from 'features/controlLayers/store/lorasSlice';
56
import {
67
clipEmbedModelSelected,
78
fluxVAESelected,
8-
modelChanged,
9+
paramsDispatch,
910
refinerModelChanged,
11+
selectActiveParams,
1012
t5EncoderModelSelected,
13+
toStore,
1114
vaeSelected,
1215
} from 'features/controlLayers/store/paramsSlice';
1316
import { refImageModelChanged, selectRefImagesSlice } from 'features/controlLayers/store/refImagesSlice';
@@ -103,7 +106,7 @@ type ModelHandler = (
103106
) => undefined;
104107

105108
const handleMainModels: ModelHandler = (models, state, dispatch, log) => {
106-
const selectedMainModel = state.params.model;
109+
const selectedMainModel = selectActiveParams(state).model;
107110
const allMainModels = models.filter(isNonRefinerMainModelConfig).sort((a) => (a.base === 'sdxl' ? -1 : 1));
108111

109112
const firstModel = allMainModels[0];
@@ -113,7 +116,7 @@ const handleMainModels: ModelHandler = (models, state, dispatch, log) => {
113116
// Only clear the model if we have one currently selected
114117
if (selectedMainModel !== null) {
115118
log.debug({ selectedMainModel }, 'No main models available, clearing');
116-
dispatch(modelChanged({ model: null }));
119+
paramsDispatch(toStore(state, dispatch), modelChanged, { model: null });
117120
}
118121
return;
119122
}
@@ -144,7 +147,7 @@ const handleMainModels: ModelHandler = (models, state, dispatch, log) => {
144147
};
145148

146149
const handleRefinerModels: ModelHandler = (models, state, dispatch, log) => {
147-
const selectedRefinerModel = state.params.refinerModel;
150+
const selectedRefinerModel = selectActiveParams(state).refinerModel;
148151

149152
// `null` is a valid refiner model - no need to do anything.
150153
if (selectedRefinerModel === null) {
@@ -163,12 +166,12 @@ const handleRefinerModels: ModelHandler = (models, state, dispatch, log) => {
163166

164167
// Else, we need to clear the refiner model
165168
log.debug({ selectedRefinerModel }, 'Selected refiner model is not available, clearing');
166-
dispatch(refinerModelChanged(null));
169+
paramsDispatch(toStore(state, dispatch), refinerModelChanged, null);
167170
return;
168171
};
169172

170173
const handleVAEModels: ModelHandler = (models, state, dispatch, log) => {
171-
const selectedVAEModel = state.params.vae;
174+
const selectedVAEModel = selectActiveParams(state).vae;
172175

173176
// `null` is a valid VAE - it means "use the VAE baked into the currently-selected main model"
174177
if (selectedVAEModel === null) {
@@ -187,7 +190,7 @@ const handleVAEModels: ModelHandler = (models, state, dispatch, log) => {
187190

188191
// Else, we need to clear the VAE model
189192
log.debug({ selectedVAEModel }, 'Selected VAE model is not available, clearing');
190-
dispatch(vaeSelected(null));
193+
paramsDispatch(toStore(state, dispatch), vaeSelected, null);
191194
return;
192195
};
193196

@@ -417,7 +420,7 @@ const handleTileControlNetModel: ModelHandler = (models, state, dispatch, log) =
417420
};
418421

419422
const handleT5EncoderModels: ModelHandler = (models, state, dispatch, log) => {
420-
const selectedT5EncoderModel = state.params.t5EncoderModel;
423+
const selectedT5EncoderModel = selectActiveParams(state).t5EncoderModel;
421424
const t5EncoderModels = models.filter((m) => isT5EncoderModelConfig(m));
422425

423426
// If the currently selected model is available, we don't need to do anything
@@ -432,20 +435,20 @@ const handleT5EncoderModels: ModelHandler = (models, state, dispatch, log) => {
432435
{ selectedT5EncoderModel, firstModel },
433436
'No selected T5 encoder model or selected T5 encoder model is not available, selecting first available model'
434437
);
435-
dispatch(t5EncoderModelSelected(zParameterT5EncoderModel.parse(firstModel)));
438+
paramsDispatch(toStore(state, dispatch), t5EncoderModelSelected, zParameterT5EncoderModel.parse(firstModel));
436439
return;
437440
}
438441

439442
// No available models, we should clear the selected model - but only if we have one selected
440443
if (selectedT5EncoderModel) {
441444
log.debug({ selectedT5EncoderModel }, 'Selected T5 encoder model is not available, clearing');
442-
dispatch(t5EncoderModelSelected(null));
445+
paramsDispatch(toStore(state, dispatch), t5EncoderModelSelected, null);
443446
return;
444447
}
445448
};
446449

447450
const handleCLIPEmbedModels: ModelHandler = (models, state, dispatch, log) => {
448-
const selectedCLIPEmbedModel = state.params.clipEmbedModel;
451+
const selectedCLIPEmbedModel = selectActiveParams(state).clipEmbedModel;
449452
const CLIPEmbedModels = models.filter((m) => isCLIPEmbedModelConfig(m));
450453

451454
// If the currently selected model is available, we don't need to do anything
@@ -460,20 +463,20 @@ const handleCLIPEmbedModels: ModelHandler = (models, state, dispatch, log) => {
460463
{ selectedCLIPEmbedModel, firstModel },
461464
'No selected CLIP embed model or selected CLIP embed model is not available, selecting first available model'
462465
);
463-
dispatch(clipEmbedModelSelected(zParameterCLIPEmbedModel.parse(firstModel)));
466+
paramsDispatch(toStore(state, dispatch), clipEmbedModelSelected, zParameterCLIPEmbedModel.parse(firstModel));
464467
return;
465468
}
466469

467470
// No available models, we should clear the selected model - but only if we have one selected
468471
if (selectedCLIPEmbedModel) {
469472
log.debug({ selectedCLIPEmbedModel }, 'Selected CLIP embed model is not available, clearing');
470-
dispatch(clipEmbedModelSelected(null));
473+
paramsDispatch(toStore(state, dispatch), clipEmbedModelSelected, null);
471474
return;
472475
}
473476
};
474477

475478
const handleFLUXVAEModels: ModelHandler = (models, state, dispatch, log) => {
476-
const selectedFLUXVAEModel = state.params.fluxVAE;
479+
const selectedFLUXVAEModel = selectActiveParams(state).fluxVAE;
477480
const fluxVAEModels = models.filter((m) => isFluxVAEModelConfig(m));
478481

479482
// If the currently selected model is available, we don't need to do anything
@@ -488,14 +491,14 @@ const handleFLUXVAEModels: ModelHandler = (models, state, dispatch, log) => {
488491
{ selectedFLUXVAEModel, firstModel },
489492
'No selected FLUX VAE model or selected FLUX VAE model is not available, selecting first available model'
490493
);
491-
dispatch(fluxVAESelected(zParameterVAEModel.parse(firstModel)));
494+
paramsDispatch(toStore(state, dispatch), fluxVAESelected, zParameterVAEModel.parse(firstModel));
492495
return;
493496
}
494497

495498
// No available models, we should clear the selected model - but only if we have one selected
496499
if (selectedFLUXVAEModel) {
497500
log.debug({ selectedFLUXVAEModel }, 'Selected FLUX VAE model is not available, clearing');
498-
dispatch(fluxVAESelected(null));
501+
paramsDispatch(toStore(state, dispatch), fluxVAESelected, null);
499502
return;
500503
}
501504
};

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

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
} from 'features/controlLayers/store/canvasStagingAreaSlice';
88
import {
99
heightChanged,
10+
paramsDispatch,
11+
selectActiveParams,
1012
setCfgRescaleMultiplier,
1113
setCfgScale,
1214
setGuidance,
@@ -37,10 +39,11 @@ import { isNonRefinerMainModelConfig } from 'services/api/types';
3739
export const addSetDefaultSettingsListener = (startAppListening: AppStartListening) => {
3840
startAppListening({
3941
actionCreator: setDefaultSettings,
40-
effect: async (action, { dispatch, getState }) => {
42+
effect: async (action, api) => {
43+
const { dispatch, getState } = api;
4144
const state = getState();
4245

43-
const currentModel = state.params.model;
46+
const currentModel = selectActiveParams(state).model;
4447

4548
if (!currentModel) {
4649
return;
@@ -64,56 +67,56 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni
6467
// we store this as "default" within default settings
6568
// to distinguish it from no default set
6669
if (vae === 'default') {
67-
dispatch(vaeSelected(null));
70+
paramsDispatch(api, vaeSelected, null);
6871
} else {
6972
const vaeModel = models.find((model) => model.key === vae);
7073
const result = zParameterVAEModel.safeParse(vaeModel);
7174
if (!result.success) {
7275
return;
7376
}
74-
dispatch(vaeSelected(result.data));
77+
paramsDispatch(api, vaeSelected, result.data);
7578
}
7679
}
7780

7881
if (vae_precision) {
7982
if (isParameterPrecision(vae_precision)) {
80-
dispatch(vaePrecisionChanged(vae_precision));
83+
paramsDispatch(api, vaePrecisionChanged, vae_precision);
8184
}
8285
}
8386

8487
if (guidance) {
8588
if (isParameterGuidance(guidance)) {
86-
dispatch(setGuidance(guidance));
89+
paramsDispatch(api, setGuidance, guidance);
8790
}
8891
}
8992

9093
if (cfg_scale) {
9194
if (isParameterCFGScale(cfg_scale)) {
92-
dispatch(setCfgScale(cfg_scale));
95+
paramsDispatch(api, setCfgScale, cfg_scale);
9396
}
9497
}
9598

9699
if (!isNil(cfg_rescale_multiplier)) {
97100
if (isParameterCFGRescaleMultiplier(cfg_rescale_multiplier)) {
98-
dispatch(setCfgRescaleMultiplier(cfg_rescale_multiplier));
101+
paramsDispatch(api, setCfgRescaleMultiplier, cfg_rescale_multiplier);
99102
}
100103
} else {
101104
// Set this to 0 if it doesn't have a default. This value is
102105
// easy to miss in the UI when users are resetting defaults
103106
// and leaving it non-zero could lead to detrimental
104107
// effects.
105-
dispatch(setCfgRescaleMultiplier(0));
108+
paramsDispatch(api, setCfgRescaleMultiplier, 0);
106109
}
107110

108111
if (steps) {
109112
if (isParameterSteps(steps)) {
110-
dispatch(setSteps(steps));
113+
paramsDispatch(api, setSteps, steps);
111114
}
112115
}
113116

114117
if (scheduler) {
115118
if (isParameterScheduler(scheduler)) {
116-
dispatch(setScheduler(scheduler));
119+
paramsDispatch(api, setScheduler, scheduler);
117120
}
118121
}
119122
const setSizeOptions = { updateAspectRatio: true, clamp: true };
@@ -125,10 +128,10 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni
125128
const activeTab = selectActiveTab(getState());
126129
if (activeTab === 'generate') {
127130
if (isParameterWidth(width)) {
128-
dispatch(widthChanged({ width, ...setSizeOptions }));
131+
paramsDispatch(api, widthChanged, { width, ...setSizeOptions });
129132
}
130133
if (isParameterHeight(height)) {
131-
dispatch(heightChanged({ height, ...setSizeOptions }));
134+
paramsDispatch(api, heightChanged, { height, ...setSizeOptions });
132135
}
133136
}
134137

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import { canvasSettingsReducer, canvasSettingsSliceConfig } from 'features/contr
2525
import { canvasSliceConfig, migrateCanvas, undoableCanvasesReducer } from 'features/controlLayers/store/canvasSlice';
2626
import { canvasSessionSliceConfig } from 'features/controlLayers/store/canvasStagingAreaSlice';
2727
import { lorasSliceConfig } from 'features/controlLayers/store/lorasSlice';
28-
import { paramsSliceConfig } from 'features/controlLayers/store/paramsSlice';
28+
import { paramsSliceConfig, paramsSliceReducer } from 'features/controlLayers/store/paramsSlice';
2929
import { refImagesSliceConfig } from 'features/controlLayers/store/refImagesSlice';
3030
import { dynamicPromptsSliceConfig } from 'features/dynamicPrompts/store/dynamicPromptsSlice';
3131
import { gallerySliceConfig } from 'features/gallery/store/gallerySlice';
@@ -98,7 +98,7 @@ const ALL_REDUCERS = {
9898
[lorasSliceConfig.slice.reducerPath]: lorasSliceConfig.slice.reducer,
9999
[modelManagerSliceConfig.slice.reducerPath]: modelManagerSliceConfig.slice.reducer,
100100
[nodesSliceConfig.slice.reducerPath]: undoableNodesSliceReducer,
101-
[paramsSliceConfig.slice.reducerPath]: paramsSliceConfig.slice.reducer,
101+
[paramsSliceConfig.slice.reducerPath]: paramsSliceReducer,
102102
[queueSliceConfig.slice.reducerPath]: queueSliceConfig.slice.reducer,
103103
[refImagesSliceConfig.slice.reducerPath]: refImagesSliceConfig.slice.reducer,
104104
[stylePresetSliceConfig.slice.reducerPath]: stylePresetSliceConfig.slice.reducer,

0 commit comments

Comments
 (0)