mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-02-19 01:54:22 -05:00
ui: redesign followups 8 (#5445)
* feat(ui): get rid of convoluted socket vs appSocket redux actions There's no need to have `socket...` and `appSocket...` actions. I did this initially due to a misunderstanding about the sequence of handling from middleware to reducers. * feat(ui): bump deps Mainly bumping to get latest `redux-remember`. A change to socket.io required a change to the types in `useSocketIO`. * chore(ui): format * feat(ui): add error handling to redux persistence layer - Add an error handler to `redux-remember` config using our logger - Add custom errors representing storage set and get failures - Update storage driver to raise these accordingly - wrap method to clear idbkeyval storage and tidy its logic up * feat(ui): add debuggingLoggerMiddleware This simply logs every action and a diff of the state change. Due to the noise this creates, it's not added by default at all. Add it to the middlewares if you want to use it. * feat(ui): add $socket to window if in dev mode * fix(ui): do not enable cancel hotkeys on inputs * fix(ui): use JSON.stringify for ROARR logger serializer A recent change to ROARR introduced limits to the size of data that will logged. This ends up making our logs far less useful. Change the serializer back to what it was previously. * feat(ui): change diff util, update debuggerLoggerMiddleware The previous diff library would present deleted things as `undefined`. Unfortunately, a JSON.stringify cycle will strip those values out. The ROARR logger does this and so the diffs end up being a lot less useful, not showing removed keys. The new diff library uses a different format for the delta that serializes nicely. * feat(ui): add migrations to redux persistence layer - All persisted slices must now have a slice config, consisting of their initial state and a migrate callback. The migrate callback is very simple for now, with no type safety. It adds missing properties to the state. A future enhancement might be to model the each slice's state with e.g. zod and have proper validation and types. - Persisted slices now have a `_version` property - The migrate callback is called inside `redux-remember`'s `unserialize` handler. I couldn't figure out a good way to put this into the reducer and do logging (reducers should have no side effects). Also I ran into a weird race condition that I couldn't figure out. And finally, the typings are tricky. This works for now. - `generationSlice` and `canvasSlice` both need migrations for the new aspect ratio setup, this has been added - Stuff related to persistence has been moved in to `store.ts` for simplicity * feat(ui): clean up StorageError class * fix(ui): scale method default is now 'auto' * feat(ui): when changing controlnet model, enable autoconfig * fix(ui): make embedding popover immediately accessible Prevents hotkeys from being captured when embeddings are still loading.
This commit is contained in:
@@ -11,6 +11,7 @@ import { STAGE_PADDING_PERCENTAGE } from 'features/canvas/util/constants';
|
||||
import floorCoordinates from 'features/canvas/util/floorCoordinates';
|
||||
import getScaledBoundingBoxDimensions from 'features/canvas/util/getScaledBoundingBoxDimensions';
|
||||
import roundDimensionsToMultiple from 'features/canvas/util/roundDimensionsToMultiple';
|
||||
import { initialAspectRatioState } from 'features/parameters/components/ImageSize/constants';
|
||||
import type { AspectRatioState } from 'features/parameters/components/ImageSize/types';
|
||||
import { modelChanged } from 'features/parameters/store/generationSlice';
|
||||
import type { PayloadActionWithOptimalDimension } from 'features/parameters/store/types';
|
||||
@@ -23,7 +24,7 @@ import { clamp, cloneDeep } from 'lodash-es';
|
||||
import type { RgbaColor } from 'react-colorful';
|
||||
import { queueApi } from 'services/api/endpoints/queue';
|
||||
import type { ImageDTO } from 'services/api/types';
|
||||
import { appSocketQueueItemStatusChanged } from 'services/events/actions';
|
||||
import { socketQueueItemStatusChanged } from 'services/events/actions';
|
||||
|
||||
import type {
|
||||
BoundingBoxScaleMethod,
|
||||
@@ -53,10 +54,11 @@ export const initialLayerState: CanvasLayerState = {
|
||||
};
|
||||
|
||||
export const initialCanvasState: CanvasState = {
|
||||
_version: 1,
|
||||
boundingBoxCoordinates: { x: 0, y: 0 },
|
||||
boundingBoxDimensions: { width: 512, height: 512 },
|
||||
boundingBoxPreviewFill: { r: 0, g: 0, b: 0, a: 0.5 },
|
||||
boundingBoxScaleMethod: 'none',
|
||||
boundingBoxScaleMethod: 'auto',
|
||||
brushColor: { r: 90, g: 90, b: 255, a: 1 },
|
||||
brushSize: 50,
|
||||
colorPickerColor: { r: 90, g: 90, b: 255, a: 1 },
|
||||
@@ -695,7 +697,7 @@ export const canvasSlice = createSlice({
|
||||
);
|
||||
});
|
||||
|
||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||
builder.addCase(socketQueueItemStatusChanged, (state, action) => {
|
||||
const batch_status = action.payload.data.batch_status;
|
||||
if (!state.batchIds.includes(batch_status.batch_id)) {
|
||||
return;
|
||||
@@ -784,3 +786,12 @@ export const {
|
||||
export default canvasSlice.reducer;
|
||||
|
||||
export const selectCanvasSlice = (state: RootState) => state.canvas;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateCanvasState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
state.aspectRatio = initialAspectRatioState;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -117,6 +117,7 @@ export const isCanvasAnyLine = (
|
||||
): obj is CanvasMaskLine | CanvasBaseLine => obj.kind === 'line';
|
||||
|
||||
export interface CanvasState {
|
||||
_version: 1;
|
||||
boundingBoxCoordinates: Vector2d;
|
||||
boundingBoxDimensions: Dimensions;
|
||||
boundingBoxPreviewFill: RgbaColor;
|
||||
|
||||
@@ -9,7 +9,7 @@ import type {
|
||||
ParameterT2IAdapterModel,
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
import { cloneDeep, merge, uniq } from 'lodash-es';
|
||||
import { appSocketInvocationError } from 'services/events/actions';
|
||||
import { socketInvocationError } from 'services/events/actions';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { controlAdapterImageProcessed } from './actions';
|
||||
@@ -51,10 +51,12 @@ export const {
|
||||
selectTotal: selectControlAdapterTotal,
|
||||
} = caAdapterSelectors;
|
||||
|
||||
export const initialControlAdapterState: ControlAdaptersState =
|
||||
export const initialControlAdaptersState: ControlAdaptersState =
|
||||
caAdapter.getInitialState<{
|
||||
_version: 1;
|
||||
pendingControlImages: string[];
|
||||
}>({
|
||||
_version: 1,
|
||||
pendingControlImages: [],
|
||||
});
|
||||
|
||||
@@ -96,7 +98,7 @@ export const selectValidT2IAdapters = (controlAdapters: ControlAdaptersState) =>
|
||||
|
||||
export const controlAdaptersSlice = createSlice({
|
||||
name: 'controlAdapters',
|
||||
initialState: initialControlAdapterState,
|
||||
initialState: initialControlAdaptersState,
|
||||
reducers: {
|
||||
controlAdapterAdded: {
|
||||
reducer: (
|
||||
@@ -267,31 +269,29 @@ export const controlAdaptersSlice = createSlice({
|
||||
|
||||
const update: Update<ControlNetConfig | T2IAdapterConfig, string> = {
|
||||
id,
|
||||
changes: { model },
|
||||
changes: { model, shouldAutoConfig: true },
|
||||
};
|
||||
|
||||
update.changes.processedControlImage = null;
|
||||
|
||||
if (cn.shouldAutoConfig) {
|
||||
let processorType: ControlAdapterProcessorType | undefined = undefined;
|
||||
let processorType: ControlAdapterProcessorType | undefined = undefined;
|
||||
|
||||
for (const modelSubstring in CONTROLADAPTER_MODEL_DEFAULT_PROCESSORS) {
|
||||
if (model.model_name.includes(modelSubstring)) {
|
||||
processorType =
|
||||
CONTROLADAPTER_MODEL_DEFAULT_PROCESSORS[modelSubstring];
|
||||
break;
|
||||
}
|
||||
for (const modelSubstring in CONTROLADAPTER_MODEL_DEFAULT_PROCESSORS) {
|
||||
if (model.model_name.includes(modelSubstring)) {
|
||||
processorType =
|
||||
CONTROLADAPTER_MODEL_DEFAULT_PROCESSORS[modelSubstring];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (processorType) {
|
||||
update.changes.processorType = processorType;
|
||||
update.changes.processorNode = CONTROLNET_PROCESSORS[processorType]
|
||||
.default as RequiredControlAdapterProcessorNode;
|
||||
} else {
|
||||
update.changes.processorType = 'none';
|
||||
update.changes.processorNode = CONTROLNET_PROCESSORS.none
|
||||
.default as RequiredControlAdapterProcessorNode;
|
||||
}
|
||||
if (processorType) {
|
||||
update.changes.processorType = processorType;
|
||||
update.changes.processorNode = CONTROLNET_PROCESSORS[processorType]
|
||||
.default as RequiredControlAdapterProcessorNode;
|
||||
} else {
|
||||
update.changes.processorType = 'none';
|
||||
update.changes.processorNode = CONTROLNET_PROCESSORS.none
|
||||
.default as RequiredControlAdapterProcessorNode;
|
||||
}
|
||||
|
||||
caAdapter.updateOne(state, update);
|
||||
@@ -435,7 +435,7 @@ export const controlAdaptersSlice = createSlice({
|
||||
caAdapter.updateOne(state, update);
|
||||
},
|
||||
controlAdaptersReset: () => {
|
||||
return cloneDeep(initialControlAdapterState);
|
||||
return cloneDeep(initialControlAdaptersState);
|
||||
},
|
||||
pendingControlImagesCleared: (state) => {
|
||||
state.pendingControlImages = [];
|
||||
@@ -454,7 +454,7 @@ export const controlAdaptersSlice = createSlice({
|
||||
}
|
||||
});
|
||||
|
||||
builder.addCase(appSocketInvocationError, (state) => {
|
||||
builder.addCase(socketInvocationError, (state) => {
|
||||
state.pendingControlImages = [];
|
||||
});
|
||||
},
|
||||
@@ -493,3 +493,11 @@ export const isAnyControlAdapterAdded = isAnyOf(
|
||||
|
||||
export const selectControlAdaptersSlice = (state: RootState) =>
|
||||
state.controlAdapters;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateControlAdaptersState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,9 @@ export const zSeedBehaviour = z.enum(['PER_ITERATION', 'PER_PROMPT']);
|
||||
export type SeedBehaviour = z.infer<typeof zSeedBehaviour>;
|
||||
export const isSeedBehaviour = (v: unknown): v is SeedBehaviour =>
|
||||
zSeedBehaviour.safeParse(v).success;
|
||||
|
||||
export interface DynamicPromptsState {
|
||||
_version: 1;
|
||||
maxPrompts: number;
|
||||
combinatorial: boolean;
|
||||
prompts: string[];
|
||||
@@ -18,6 +20,7 @@ export interface DynamicPromptsState {
|
||||
}
|
||||
|
||||
export const initialDynamicPromptsState: DynamicPromptsState = {
|
||||
_version: 1,
|
||||
maxPrompts: 100,
|
||||
combinatorial: true,
|
||||
prompts: [],
|
||||
@@ -78,3 +81,11 @@ export default dynamicPromptsSlice.reducer;
|
||||
|
||||
export const selectDynamicPromptsSlice = (state: RootState) =>
|
||||
state.dynamicPrompts;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateDynamicPromptsState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { ChakraProps } from '@chakra-ui/react';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InvControl } from 'common/components/InvControl/InvControl';
|
||||
import { InvSelect } from 'common/components/InvSelect/InvSelect';
|
||||
import { InvSelectFallback } from 'common/components/InvSelect/InvSelectFallback';
|
||||
import { useGroupedModelInvSelect } from 'common/components/InvSelect/useGroupedModelInvSelect';
|
||||
import type { EmbeddingSelectProps } from 'features/embedding/types';
|
||||
import { t } from 'i18next';
|
||||
@@ -47,23 +46,16 @@ export const EmbeddingSelect = memo(
|
||||
onChange: _onChange,
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return <InvSelectFallback label={t('common.loading')} />;
|
||||
}
|
||||
|
||||
if (options.length === 0) {
|
||||
return <InvSelectFallback label={t('embedding.noEmbeddingsLoaded')} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<InvControl isDisabled={!options.length}>
|
||||
<InvControl>
|
||||
<InvSelect
|
||||
placeholder={t('embedding.addEmbedding')}
|
||||
placeholder={
|
||||
isLoading ? t('common.loading') : t('embedding.addEmbedding')
|
||||
}
|
||||
defaultMenuIsOpen
|
||||
autoFocus
|
||||
value={null}
|
||||
options={options}
|
||||
isDisabled={!options.length}
|
||||
noOptionsMessage={noOptionsMessage}
|
||||
onChange={onChange}
|
||||
onMenuClose={onClose}
|
||||
|
||||
@@ -106,3 +106,11 @@ const isAnyBoardDeleted = isAnyOf(
|
||||
);
|
||||
|
||||
export const selectGallerySlice = (state: RootState) => state.gallery;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateGalleryState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -7,12 +7,14 @@ import type {
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
|
||||
export interface HRFState {
|
||||
_version: 1;
|
||||
hrfEnabled: boolean;
|
||||
hrfStrength: ParameterStrength;
|
||||
hrfMethod: ParameterHRFMethod;
|
||||
}
|
||||
|
||||
export const initialHRFState: HRFState = {
|
||||
_version: 1,
|
||||
hrfStrength: 0.45,
|
||||
hrfEnabled: false,
|
||||
hrfMethod: 'ESRGAN',
|
||||
@@ -41,3 +43,11 @@ export const { setHrfEnabled, setHrfStrength, setHrfMethod } = hrfSlice.actions;
|
||||
export default hrfSlice.reducer;
|
||||
|
||||
export const selectHrfSlice = (state: RootState) => state.hrf;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateHRFState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -14,16 +14,18 @@ export const defaultLoRAConfig = {
|
||||
};
|
||||
|
||||
export type LoraState = {
|
||||
_version: 1;
|
||||
loras: Record<string, LoRA>;
|
||||
};
|
||||
|
||||
export const intialLoraState: LoraState = {
|
||||
export const initialLoraState: LoraState = {
|
||||
_version: 1,
|
||||
loras: {},
|
||||
};
|
||||
|
||||
export const loraSlice = createSlice({
|
||||
name: 'lora',
|
||||
initialState: intialLoraState,
|
||||
initialState: initialLoraState,
|
||||
reducers: {
|
||||
loraAdded: (state, action: PayloadAction<LoRAModelConfigEntity>) => {
|
||||
const { model_name, id, base_model } = action.payload;
|
||||
@@ -77,3 +79,11 @@ export const {
|
||||
export default loraSlice.reducer;
|
||||
|
||||
export const selectLoraSlice = (state: RootState) => state.lora;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateLoRAState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -3,11 +3,13 @@ import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { RootState } from 'app/store/store';
|
||||
|
||||
type ModelManagerState = {
|
||||
_version: 1;
|
||||
searchFolder: string | null;
|
||||
advancedAddScanModel: string | null;
|
||||
};
|
||||
|
||||
const initialModelManagerState: ModelManagerState = {
|
||||
export const initialModelManagerState: ModelManagerState = {
|
||||
_version: 1,
|
||||
searchFolder: null,
|
||||
advancedAddScanModel: null,
|
||||
};
|
||||
@@ -31,3 +33,11 @@ export const { setSearchFolder, setAdvancedAddScanModel } =
|
||||
export default modelManagerSlice.reducer;
|
||||
|
||||
export const selectModelManagerSlice = (state: RootState) => state.modelmanager;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateModelManagerState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -74,11 +74,11 @@ import {
|
||||
} from 'reactflow';
|
||||
import { receivedOpenAPISchema } from 'services/api/thunks/schema';
|
||||
import {
|
||||
appSocketGeneratorProgress,
|
||||
appSocketInvocationComplete,
|
||||
appSocketInvocationError,
|
||||
appSocketInvocationStarted,
|
||||
appSocketQueueItemStatusChanged,
|
||||
socketGeneratorProgress,
|
||||
socketInvocationComplete,
|
||||
socketInvocationError,
|
||||
socketInvocationStarted,
|
||||
socketQueueItemStatusChanged,
|
||||
} from 'services/events/actions';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import type { z } from 'zod';
|
||||
@@ -96,6 +96,7 @@ const initialNodeExecutionState: Omit<NodeExecutionState, 'nodeId'> = {
|
||||
};
|
||||
|
||||
export const initialNodesState: NodesState = {
|
||||
_version: 1,
|
||||
nodes: [],
|
||||
edges: [],
|
||||
isReady: false,
|
||||
@@ -838,14 +839,14 @@ const nodesSlice = createSlice({
|
||||
}, {});
|
||||
});
|
||||
|
||||
builder.addCase(appSocketInvocationStarted, (state, action) => {
|
||||
builder.addCase(socketInvocationStarted, (state, action) => {
|
||||
const { source_node_id } = action.payload.data;
|
||||
const node = state.nodeExecutionStates[source_node_id];
|
||||
if (node) {
|
||||
node.status = zNodeStatus.enum.IN_PROGRESS;
|
||||
}
|
||||
});
|
||||
builder.addCase(appSocketInvocationComplete, (state, action) => {
|
||||
builder.addCase(socketInvocationComplete, (state, action) => {
|
||||
const { source_node_id, result } = action.payload.data;
|
||||
const nes = state.nodeExecutionStates[source_node_id];
|
||||
if (nes) {
|
||||
@@ -856,7 +857,7 @@ const nodesSlice = createSlice({
|
||||
nes.outputs.push(result);
|
||||
}
|
||||
});
|
||||
builder.addCase(appSocketInvocationError, (state, action) => {
|
||||
builder.addCase(socketInvocationError, (state, action) => {
|
||||
const { source_node_id } = action.payload.data;
|
||||
const node = state.nodeExecutionStates[source_node_id];
|
||||
if (node) {
|
||||
@@ -866,7 +867,7 @@ const nodesSlice = createSlice({
|
||||
node.progressImage = null;
|
||||
}
|
||||
});
|
||||
builder.addCase(appSocketGeneratorProgress, (state, action) => {
|
||||
builder.addCase(socketGeneratorProgress, (state, action) => {
|
||||
const { source_node_id, step, total_steps, progress_image } =
|
||||
action.payload.data;
|
||||
const node = state.nodeExecutionStates[source_node_id];
|
||||
@@ -876,7 +877,7 @@ const nodesSlice = createSlice({
|
||||
node.progressImage = progress_image ?? null;
|
||||
}
|
||||
});
|
||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||
builder.addCase(socketQueueItemStatusChanged, (state, action) => {
|
||||
if (['in_progress'].includes(action.payload.data.queue_item.status)) {
|
||||
forEach(state.nodeExecutionStates, (nes) => {
|
||||
nes.status = zNodeStatus.enum.PENDING;
|
||||
@@ -990,3 +991,11 @@ export const isAnyNodeOrEdgeMutation = isAnyOf(
|
||||
export default nodesSlice.reducer;
|
||||
|
||||
export const selectNodesSlice = (state: RootState) => state.nodes;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateNodesState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
} from 'reactflow';
|
||||
|
||||
export type NodesState = {
|
||||
_version: 1;
|
||||
nodes: AnyNode[];
|
||||
edges: InvocationNodeEdge[];
|
||||
connectionStartParams: OnConnectStartParams | null;
|
||||
@@ -39,6 +40,7 @@ export type NodesState = {
|
||||
};
|
||||
|
||||
export type WorkflowsState = Omit<WorkflowV2, 'nodes' | 'edges'> & {
|
||||
_version: 1;
|
||||
isTouched: boolean;
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import type { FieldIdentifier } from 'features/nodes/types/field';
|
||||
import { cloneDeep, isEqual, uniqBy } from 'lodash-es';
|
||||
|
||||
export const initialWorkflowState: WorkflowState = {
|
||||
_version: 1,
|
||||
name: '',
|
||||
author: '',
|
||||
description: '',
|
||||
@@ -86,7 +87,7 @@ const workflowSlice = createSlice({
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(workflowLoaded, (state, action) => {
|
||||
const { nodes: _nodes, edges: _edges, ...workflowExtra } = action.payload;
|
||||
return { ...cloneDeep(workflowExtra), isTouched: true };
|
||||
return { ...initialWorkflowState, ...cloneDeep(workflowExtra) };
|
||||
});
|
||||
|
||||
builder.addCase(nodesDeleted, (state, action) => {
|
||||
@@ -123,3 +124,11 @@ export const {
|
||||
export default workflowSlice.reducer;
|
||||
|
||||
export const selectWorkflowSlice = (state: RootState) => state.workflow;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateWorkflowState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -29,6 +29,7 @@ import type { ImageDTO } from 'services/api/types';
|
||||
import type { GenerationState } from './types';
|
||||
|
||||
export const initialGenerationState: GenerationState = {
|
||||
_version: 1,
|
||||
cfgScale: 7.5,
|
||||
cfgRescaleMultiplier: 0,
|
||||
height: 512,
|
||||
@@ -276,3 +277,12 @@ export const { selectOptimalDimension } = generationSlice.selectors;
|
||||
export default generationSlice.reducer;
|
||||
|
||||
export const selectGenerationSlice = (state: RootState) => state.generation;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateGenerationState = (state: any): GenerationState => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
state.aspectRatio = initialAspectRatioState;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -14,10 +14,12 @@ export const isParamESRGANModelName = (v: unknown): v is ParamESRGANModelName =>
|
||||
zParamESRGANModelName.safeParse(v).success;
|
||||
|
||||
export interface PostprocessingState {
|
||||
_version: 1;
|
||||
esrganModelName: ParamESRGANModelName;
|
||||
}
|
||||
|
||||
export const initialPostprocessingState: PostprocessingState = {
|
||||
_version: 1,
|
||||
esrganModelName: 'RealESRGAN_x4plus.pth',
|
||||
};
|
||||
|
||||
@@ -40,3 +42,11 @@ export default postprocessingSlice.reducer;
|
||||
|
||||
export const selectPostprocessingSlice = (state: RootState) =>
|
||||
state.postprocessing;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migratePostprocessingState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@ import type {
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
|
||||
export interface GenerationState {
|
||||
_version: 1;
|
||||
cfgScale: ParameterCFGScale;
|
||||
cfgRescaleMultiplier: ParameterCFGRescaleMultiplier;
|
||||
height: ParameterHeight;
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
|
||||
type SDXLState = {
|
||||
_version: 1;
|
||||
positiveStylePrompt: ParameterPositiveStylePromptSDXL;
|
||||
negativeStylePrompt: ParameterNegativeStylePromptSDXL;
|
||||
shouldConcatSDXLStylePrompt: boolean;
|
||||
@@ -22,6 +23,7 @@ type SDXLState = {
|
||||
};
|
||||
|
||||
export const initialSDXLState: SDXLState = {
|
||||
_version: 1,
|
||||
positiveStylePrompt: '',
|
||||
negativeStylePrompt: '',
|
||||
shouldConcatSDXLStylePrompt: true,
|
||||
@@ -96,3 +98,11 @@ export const {
|
||||
export default sdxlSlice.reducer;
|
||||
|
||||
export const selectSdxlSlice = (state: RootState) => state.sdxl;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateSDXLState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -8,23 +8,24 @@ import { t } from 'i18next';
|
||||
import { startCase } from 'lodash-es';
|
||||
import type { LogLevelName } from 'roarr';
|
||||
import {
|
||||
appSocketConnected,
|
||||
appSocketDisconnected,
|
||||
appSocketGeneratorProgress,
|
||||
appSocketGraphExecutionStateComplete,
|
||||
appSocketInvocationComplete,
|
||||
appSocketInvocationError,
|
||||
appSocketInvocationRetrievalError,
|
||||
appSocketInvocationStarted,
|
||||
appSocketModelLoadCompleted,
|
||||
appSocketModelLoadStarted,
|
||||
appSocketQueueItemStatusChanged,
|
||||
appSocketSessionRetrievalError,
|
||||
socketConnected,
|
||||
socketDisconnected,
|
||||
socketGeneratorProgress,
|
||||
socketGraphExecutionStateComplete,
|
||||
socketInvocationComplete,
|
||||
socketInvocationError,
|
||||
socketInvocationRetrievalError,
|
||||
socketInvocationStarted,
|
||||
socketModelLoadCompleted,
|
||||
socketModelLoadStarted,
|
||||
socketQueueItemStatusChanged,
|
||||
socketSessionRetrievalError,
|
||||
} from 'services/events/actions';
|
||||
|
||||
import type { Language, SystemState } from './types';
|
||||
|
||||
export const initialSystemState: SystemState = {
|
||||
_version: 1,
|
||||
isInitialized: false,
|
||||
isConnected: false,
|
||||
shouldConfirmOnDelete: true,
|
||||
@@ -92,7 +93,7 @@ export const systemSlice = createSlice({
|
||||
/**
|
||||
* Socket Connected
|
||||
*/
|
||||
builder.addCase(appSocketConnected, (state) => {
|
||||
builder.addCase(socketConnected, (state) => {
|
||||
state.isConnected = true;
|
||||
state.denoiseProgress = null;
|
||||
state.status = 'CONNECTED';
|
||||
@@ -101,7 +102,7 @@ export const systemSlice = createSlice({
|
||||
/**
|
||||
* Socket Disconnected
|
||||
*/
|
||||
builder.addCase(appSocketDisconnected, (state) => {
|
||||
builder.addCase(socketDisconnected, (state) => {
|
||||
state.isConnected = false;
|
||||
state.denoiseProgress = null;
|
||||
state.status = 'DISCONNECTED';
|
||||
@@ -110,7 +111,7 @@ export const systemSlice = createSlice({
|
||||
/**
|
||||
* Invocation Started
|
||||
*/
|
||||
builder.addCase(appSocketInvocationStarted, (state) => {
|
||||
builder.addCase(socketInvocationStarted, (state) => {
|
||||
state.denoiseProgress = null;
|
||||
state.status = 'PROCESSING';
|
||||
});
|
||||
@@ -118,7 +119,7 @@ export const systemSlice = createSlice({
|
||||
/**
|
||||
* Generator Progress
|
||||
*/
|
||||
builder.addCase(appSocketGeneratorProgress, (state, action) => {
|
||||
builder.addCase(socketGeneratorProgress, (state, action) => {
|
||||
const {
|
||||
step,
|
||||
total_steps,
|
||||
@@ -144,7 +145,7 @@ export const systemSlice = createSlice({
|
||||
/**
|
||||
* Invocation Complete
|
||||
*/
|
||||
builder.addCase(appSocketInvocationComplete, (state) => {
|
||||
builder.addCase(socketInvocationComplete, (state) => {
|
||||
state.denoiseProgress = null;
|
||||
state.status = 'CONNECTED';
|
||||
});
|
||||
@@ -152,20 +153,20 @@ export const systemSlice = createSlice({
|
||||
/**
|
||||
* Graph Execution State Complete
|
||||
*/
|
||||
builder.addCase(appSocketGraphExecutionStateComplete, (state) => {
|
||||
builder.addCase(socketGraphExecutionStateComplete, (state) => {
|
||||
state.denoiseProgress = null;
|
||||
state.status = 'CONNECTED';
|
||||
});
|
||||
|
||||
builder.addCase(appSocketModelLoadStarted, (state) => {
|
||||
builder.addCase(socketModelLoadStarted, (state) => {
|
||||
state.status = 'LOADING_MODEL';
|
||||
});
|
||||
|
||||
builder.addCase(appSocketModelLoadCompleted, (state) => {
|
||||
builder.addCase(socketModelLoadCompleted, (state) => {
|
||||
state.status = 'CONNECTED';
|
||||
});
|
||||
|
||||
builder.addCase(appSocketQueueItemStatusChanged, (state, action) => {
|
||||
builder.addCase(socketQueueItemStatusChanged, (state, action) => {
|
||||
if (
|
||||
['completed', 'canceled', 'failed'].includes(
|
||||
action.payload.data.queue_item.status
|
||||
@@ -211,9 +212,17 @@ export const {
|
||||
export default systemSlice.reducer;
|
||||
|
||||
const isAnyServerError = isAnyOf(
|
||||
appSocketInvocationError,
|
||||
appSocketSessionRetrievalError,
|
||||
appSocketInvocationRetrievalError
|
||||
socketInvocationError,
|
||||
socketSessionRetrievalError,
|
||||
socketInvocationRetrievalError
|
||||
);
|
||||
|
||||
export const selectSystemSlice = (state: RootState) => state.system;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateSystemState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -43,6 +43,7 @@ export const isLanguage = (v: unknown): v is Language =>
|
||||
zLanguage.safeParse(v).success;
|
||||
|
||||
export interface SystemState {
|
||||
_version: 1;
|
||||
isInitialized: boolean;
|
||||
isConnected: boolean;
|
||||
shouldConfirmOnDelete: boolean;
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { InvokeTabName } from './tabMap';
|
||||
import type { UIState } from './uiTypes';
|
||||
|
||||
export const initialUIState: UIState = {
|
||||
_version: 1,
|
||||
activeTab: 'txt2img',
|
||||
shouldShowImageDetails: false,
|
||||
shouldShowExistingModelsInSearch: false,
|
||||
@@ -63,3 +64,11 @@ export const {
|
||||
export default uiSlice.reducer;
|
||||
|
||||
export const selectUiSlice = (state: RootState) => state.ui;
|
||||
|
||||
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
|
||||
export const migrateUIState = (state: any): any => {
|
||||
if (!('_version' in state)) {
|
||||
state._version = 1;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { InvokeTabName } from './tabMap';
|
||||
|
||||
export interface UIState {
|
||||
_version: 1;
|
||||
activeTab: InvokeTabName;
|
||||
shouldShowImageDetails: boolean;
|
||||
shouldShowExistingModelsInSearch: boolean;
|
||||
|
||||
Reference in New Issue
Block a user