mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): being dismantling old sio stuff, fix recall seed/prompt/init
- still need to fix up metadataviewer's recall features
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
|
import React, { lazy, memo, PropsWithChildren, useEffect } from 'react';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import { PersistGate } from 'redux-persist/integration/react';
|
import { PersistGate } from 'redux-persist/integration/react';
|
||||||
import { buildMiddleware, store } from 'app/store/store';
|
import { store } from 'app/store/store';
|
||||||
import { persistor } from '../store/persistor';
|
import { persistor } from '../store/persistor';
|
||||||
import { OpenAPI } from 'services/api';
|
import { OpenAPI } from 'services/api';
|
||||||
import '@fontsource/inter/100.css';
|
import '@fontsource/inter/100.css';
|
||||||
@ -19,6 +19,7 @@ import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares';
|
|||||||
import { PartialAppConfig } from 'app/types/invokeai';
|
import { PartialAppConfig } from 'app/types/invokeai';
|
||||||
|
|
||||||
import '../../i18n';
|
import '../../i18n';
|
||||||
|
import { socketMiddleware } from 'services/events/middleware';
|
||||||
|
|
||||||
const App = lazy(() => import('./App'));
|
const App = lazy(() => import('./App'));
|
||||||
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
const ThemeLocaleProvider = lazy(() => import('./ThemeLocaleProvider'));
|
||||||
@ -50,7 +51,7 @@ const InvokeAIUI = ({ apiUrl, token, config, children }: Props) => {
|
|||||||
// the `apiUrl`/`token` dynamically.
|
// the `apiUrl`/`token` dynamically.
|
||||||
|
|
||||||
// rebuild socket middleware with token and apiUrl
|
// rebuild socket middleware with token and apiUrl
|
||||||
addMiddleware(buildMiddleware());
|
addMiddleware(socketMiddleware());
|
||||||
}, [apiUrl, token]);
|
}, [apiUrl, token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
// TODO: use Enums?
|
// TODO: use Enums?
|
||||||
|
|
||||||
import { InProgressImageType } from 'features/system/store/systemSlice';
|
|
||||||
|
|
||||||
export const DIFFUSERS_SCHEDULERS: Array<string> = [
|
export const DIFFUSERS_SCHEDULERS: Array<string> = [
|
||||||
'ddim',
|
'ddim',
|
||||||
'plms',
|
'plms',
|
||||||
@ -33,17 +31,8 @@ export const UPSCALING_LEVELS: Array<{ key: string; value: number }> = [
|
|||||||
|
|
||||||
export const NUMPY_RAND_MIN = 0;
|
export const NUMPY_RAND_MIN = 0;
|
||||||
|
|
||||||
export const NUMPY_RAND_MAX = 4294967295;
|
export const NUMPY_RAND_MAX = 2147483647;
|
||||||
|
|
||||||
export const FACETOOL_TYPES = ['gfpgan', 'codeformer'] as const;
|
export const FACETOOL_TYPES = ['gfpgan', 'codeformer'] as const;
|
||||||
|
|
||||||
export const IN_PROGRESS_IMAGE_TYPES: Array<{
|
|
||||||
key: string;
|
|
||||||
value: InProgressImageType;
|
|
||||||
}> = [
|
|
||||||
{ key: 'None', value: 'none' },
|
|
||||||
{ key: 'Fast', value: 'latents' },
|
|
||||||
{ key: 'Accurate', value: 'full-res' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const NODE_MIN_WIDTH = 250;
|
export const NODE_MIN_WIDTH = 250;
|
||||||
|
@ -1,65 +1,67 @@
|
|||||||
import { createAction } from '@reduxjs/toolkit';
|
// import { createAction } from '@reduxjs/toolkit';
|
||||||
import * as InvokeAI from 'app/types/invokeai';
|
// import * as InvokeAI from 'app/types/invokeai';
|
||||||
import { GalleryCategory } from 'features/gallery/store/gallerySlice';
|
// import { GalleryCategory } from 'features/gallery/store/gallerySlice';
|
||||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
// import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* We can't use redux-toolkit's createSlice() to make these actions,
|
// * We can't use redux-toolkit's createSlice() to make these actions,
|
||||||
* because they have no associated reducer. They only exist to dispatch
|
// * because they have no associated reducer. They only exist to dispatch
|
||||||
* requests to the server via socketio. These actions will be handled
|
// * requests to the server via socketio. These actions will be handled
|
||||||
* by the middleware.
|
// * by the middleware.
|
||||||
*/
|
// */
|
||||||
|
|
||||||
export const generateImage = createAction<InvokeTabName>(
|
// export const generateImage = createAction<InvokeTabName>(
|
||||||
'socketio/generateImage'
|
// 'socketio/generateImage'
|
||||||
);
|
// );
|
||||||
export const runESRGAN = createAction<InvokeAI._Image>('socketio/runESRGAN');
|
// export const runESRGAN = createAction<InvokeAI._Image>('socketio/runESRGAN');
|
||||||
export const runFacetool = createAction<InvokeAI._Image>(
|
// export const runFacetool = createAction<InvokeAI._Image>(
|
||||||
'socketio/runFacetool'
|
// 'socketio/runFacetool'
|
||||||
);
|
// );
|
||||||
export const deleteImage = createAction<InvokeAI._Image>(
|
// export const deleteImage = createAction<InvokeAI._Image>(
|
||||||
'socketio/deleteImage'
|
// 'socketio/deleteImage'
|
||||||
);
|
// );
|
||||||
export const requestImages = createAction<GalleryCategory>(
|
// export const requestImages = createAction<GalleryCategory>(
|
||||||
'socketio/requestImages'
|
// 'socketio/requestImages'
|
||||||
);
|
// );
|
||||||
export const requestNewImages = createAction<GalleryCategory>(
|
// export const requestNewImages = createAction<GalleryCategory>(
|
||||||
'socketio/requestNewImages'
|
// 'socketio/requestNewImages'
|
||||||
);
|
// );
|
||||||
export const cancelProcessing = createAction<undefined>(
|
// export const cancelProcessing = createAction<undefined>(
|
||||||
'socketio/cancelProcessing'
|
// 'socketio/cancelProcessing'
|
||||||
);
|
// );
|
||||||
|
|
||||||
export const requestSystemConfig = createAction<undefined>(
|
// export const requestSystemConfig = createAction<undefined>(
|
||||||
'socketio/requestSystemConfig'
|
// 'socketio/requestSystemConfig'
|
||||||
);
|
// );
|
||||||
|
|
||||||
export const searchForModels = createAction<string>('socketio/searchForModels');
|
// export const searchForModels = createAction<string>('socketio/searchForModels');
|
||||||
|
|
||||||
export const addNewModel = createAction<
|
// export const addNewModel = createAction<
|
||||||
InvokeAI.InvokeModelConfigProps | InvokeAI.InvokeDiffusersModelConfigProps
|
// InvokeAI.InvokeModelConfigProps | InvokeAI.InvokeDiffusersModelConfigProps
|
||||||
>('socketio/addNewModel');
|
// >('socketio/addNewModel');
|
||||||
|
|
||||||
export const deleteModel = createAction<string>('socketio/deleteModel');
|
// export const deleteModel = createAction<string>('socketio/deleteModel');
|
||||||
|
|
||||||
export const convertToDiffusers =
|
// export const convertToDiffusers =
|
||||||
createAction<InvokeAI.InvokeModelConversionProps>(
|
// createAction<InvokeAI.InvokeModelConversionProps>(
|
||||||
'socketio/convertToDiffusers'
|
// 'socketio/convertToDiffusers'
|
||||||
);
|
// );
|
||||||
|
|
||||||
export const mergeDiffusersModels =
|
// export const mergeDiffusersModels =
|
||||||
createAction<InvokeAI.InvokeModelMergingProps>(
|
// createAction<InvokeAI.InvokeModelMergingProps>(
|
||||||
'socketio/mergeDiffusersModels'
|
// 'socketio/mergeDiffusersModels'
|
||||||
);
|
// );
|
||||||
|
|
||||||
export const requestModelChange = createAction<string>(
|
// export const requestModelChange = createAction<string>(
|
||||||
'socketio/requestModelChange'
|
// 'socketio/requestModelChange'
|
||||||
);
|
// );
|
||||||
|
|
||||||
export const saveStagingAreaImageToGallery = createAction<string>(
|
// export const saveStagingAreaImageToGallery = createAction<string>(
|
||||||
'socketio/saveStagingAreaImageToGallery'
|
// 'socketio/saveStagingAreaImageToGallery'
|
||||||
);
|
// );
|
||||||
|
|
||||||
export const emptyTempFolder = createAction<undefined>(
|
// export const emptyTempFolder = createAction<undefined>(
|
||||||
'socketio/requestEmptyTempFolder'
|
// 'socketio/requestEmptyTempFolder'
|
||||||
);
|
// );
|
||||||
|
|
||||||
|
export default {};
|
||||||
|
@ -1,207 +1,209 @@
|
|||||||
import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
// import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
||||||
import * as InvokeAI from 'app/types/invokeai';
|
// import * as InvokeAI from 'app/types/invokeai';
|
||||||
import type { RootState } from 'app/store/store';
|
// import type { RootState } from 'app/store/store';
|
||||||
import {
|
// import {
|
||||||
frontendToBackendParameters,
|
// frontendToBackendParameters,
|
||||||
FrontendToBackendParametersConfig,
|
// FrontendToBackendParametersConfig,
|
||||||
} from 'common/util/parameterTranslation';
|
// } from 'common/util/parameterTranslation';
|
||||||
import dateFormat from 'dateformat';
|
// import dateFormat from 'dateformat';
|
||||||
import {
|
// import {
|
||||||
GalleryCategory,
|
// GalleryCategory,
|
||||||
GalleryState,
|
// GalleryState,
|
||||||
removeImage,
|
// removeImage,
|
||||||
} from 'features/gallery/store/gallerySlice';
|
// } from 'features/gallery/store/gallerySlice';
|
||||||
import {
|
// import {
|
||||||
generationRequested,
|
// generationRequested,
|
||||||
modelChangeRequested,
|
// modelChangeRequested,
|
||||||
modelConvertRequested,
|
// modelConvertRequested,
|
||||||
modelMergingRequested,
|
// modelMergingRequested,
|
||||||
setIsProcessing,
|
// setIsProcessing,
|
||||||
} from 'features/system/store/systemSlice';
|
// } from 'features/system/store/systemSlice';
|
||||||
import { InvokeTabName } from 'features/ui/store/tabMap';
|
// import { InvokeTabName } from 'features/ui/store/tabMap';
|
||||||
import { Socket } from 'socket.io-client';
|
// import { Socket } from 'socket.io-client';
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Returns an object containing all functions which use `socketio.emit()`.
|
// * Returns an object containing all functions which use `socketio.emit()`.
|
||||||
* i.e. those which make server requests.
|
// * i.e. those which make server requests.
|
||||||
*/
|
// */
|
||||||
const makeSocketIOEmitters = (
|
// const makeSocketIOEmitters = (
|
||||||
store: MiddlewareAPI<Dispatch<AnyAction>, RootState>,
|
// store: MiddlewareAPI<Dispatch<AnyAction>, RootState>,
|
||||||
socketio: Socket
|
// socketio: Socket
|
||||||
) => {
|
// ) => {
|
||||||
// We need to dispatch actions to redux and get pieces of state from the store.
|
// // We need to dispatch actions to redux and get pieces of state from the store.
|
||||||
const { dispatch, getState } = store;
|
// const { dispatch, getState } = store;
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
emitGenerateImage: (generationMode: InvokeTabName) => {
|
// emitGenerateImage: (generationMode: InvokeTabName) => {
|
||||||
dispatch(setIsProcessing(true));
|
// dispatch(setIsProcessing(true));
|
||||||
|
|
||||||
const state: RootState = getState();
|
// const state: RootState = getState();
|
||||||
|
|
||||||
const {
|
// const {
|
||||||
generation: generationState,
|
// generation: generationState,
|
||||||
postprocessing: postprocessingState,
|
// postprocessing: postprocessingState,
|
||||||
system: systemState,
|
// system: systemState,
|
||||||
canvas: canvasState,
|
// canvas: canvasState,
|
||||||
} = state;
|
// } = state;
|
||||||
|
|
||||||
const frontendToBackendParametersConfig: FrontendToBackendParametersConfig =
|
// const frontendToBackendParametersConfig: FrontendToBackendParametersConfig =
|
||||||
{
|
// {
|
||||||
generationMode,
|
// generationMode,
|
||||||
generationState,
|
// generationState,
|
||||||
postprocessingState,
|
// postprocessingState,
|
||||||
canvasState,
|
// canvasState,
|
||||||
systemState,
|
// systemState,
|
||||||
};
|
// };
|
||||||
|
|
||||||
dispatch(generationRequested());
|
// dispatch(generationRequested());
|
||||||
|
|
||||||
const { generationParameters, esrganParameters, facetoolParameters } =
|
// const { generationParameters, esrganParameters, facetoolParameters } =
|
||||||
frontendToBackendParameters(frontendToBackendParametersConfig);
|
// frontendToBackendParameters(frontendToBackendParametersConfig);
|
||||||
|
|
||||||
socketio.emit(
|
// socketio.emit(
|
||||||
'generateImage',
|
// 'generateImage',
|
||||||
generationParameters,
|
// generationParameters,
|
||||||
esrganParameters,
|
// esrganParameters,
|
||||||
facetoolParameters
|
// facetoolParameters
|
||||||
);
|
// );
|
||||||
|
|
||||||
// we need to truncate the init_mask base64 else it takes up the whole log
|
// // we need to truncate the init_mask base64 else it takes up the whole log
|
||||||
// TODO: handle maintaining masks for reproducibility in future
|
// // TODO: handle maintaining masks for reproducibility in future
|
||||||
if (generationParameters.init_mask) {
|
// if (generationParameters.init_mask) {
|
||||||
generationParameters.init_mask = generationParameters.init_mask
|
// generationParameters.init_mask = generationParameters.init_mask
|
||||||
.substr(0, 64)
|
// .substr(0, 64)
|
||||||
.concat('...');
|
// .concat('...');
|
||||||
}
|
// }
|
||||||
if (generationParameters.init_img) {
|
// if (generationParameters.init_img) {
|
||||||
generationParameters.init_img = generationParameters.init_img
|
// generationParameters.init_img = generationParameters.init_img
|
||||||
.substr(0, 64)
|
// .substr(0, 64)
|
||||||
.concat('...');
|
// .concat('...');
|
||||||
}
|
// }
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Image generation requested: ${JSON.stringify({
|
// message: `Image generation requested: ${JSON.stringify({
|
||||||
...generationParameters,
|
// ...generationParameters,
|
||||||
...esrganParameters,
|
// ...esrganParameters,
|
||||||
...facetoolParameters,
|
// ...facetoolParameters,
|
||||||
})}`,
|
// })}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
emitRunESRGAN: (imageToProcess: InvokeAI._Image) => {
|
// emitRunESRGAN: (imageToProcess: InvokeAI._Image) => {
|
||||||
dispatch(setIsProcessing(true));
|
// dispatch(setIsProcessing(true));
|
||||||
|
|
||||||
const {
|
// const {
|
||||||
postprocessing: {
|
// postprocessing: {
|
||||||
upscalingLevel,
|
// upscalingLevel,
|
||||||
upscalingDenoising,
|
// upscalingDenoising,
|
||||||
upscalingStrength,
|
// upscalingStrength,
|
||||||
},
|
// },
|
||||||
} = getState();
|
// } = getState();
|
||||||
|
|
||||||
const esrganParameters = {
|
// const esrganParameters = {
|
||||||
upscale: [upscalingLevel, upscalingDenoising, upscalingStrength],
|
// upscale: [upscalingLevel, upscalingDenoising, upscalingStrength],
|
||||||
};
|
// };
|
||||||
socketio.emit('runPostprocessing', imageToProcess, {
|
// socketio.emit('runPostprocessing', imageToProcess, {
|
||||||
type: 'esrgan',
|
// type: 'esrgan',
|
||||||
...esrganParameters,
|
// ...esrganParameters,
|
||||||
});
|
// });
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `ESRGAN upscale requested: ${JSON.stringify({
|
// message: `ESRGAN upscale requested: ${JSON.stringify({
|
||||||
file: imageToProcess.url,
|
// file: imageToProcess.url,
|
||||||
...esrganParameters,
|
// ...esrganParameters,
|
||||||
})}`,
|
// })}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
emitRunFacetool: (imageToProcess: InvokeAI._Image) => {
|
// emitRunFacetool: (imageToProcess: InvokeAI._Image) => {
|
||||||
dispatch(setIsProcessing(true));
|
// dispatch(setIsProcessing(true));
|
||||||
|
|
||||||
const {
|
// const {
|
||||||
postprocessing: { facetoolType, facetoolStrength, codeformerFidelity },
|
// postprocessing: { facetoolType, facetoolStrength, codeformerFidelity },
|
||||||
} = getState();
|
// } = getState();
|
||||||
|
|
||||||
const facetoolParameters: Record<string, unknown> = {
|
// const facetoolParameters: Record<string, unknown> = {
|
||||||
facetool_strength: facetoolStrength,
|
// facetool_strength: facetoolStrength,
|
||||||
};
|
// };
|
||||||
|
|
||||||
if (facetoolType === 'codeformer') {
|
// if (facetoolType === 'codeformer') {
|
||||||
facetoolParameters.codeformer_fidelity = codeformerFidelity;
|
// facetoolParameters.codeformer_fidelity = codeformerFidelity;
|
||||||
}
|
// }
|
||||||
|
|
||||||
socketio.emit('runPostprocessing', imageToProcess, {
|
// socketio.emit('runPostprocessing', imageToProcess, {
|
||||||
type: facetoolType,
|
// type: facetoolType,
|
||||||
...facetoolParameters,
|
// ...facetoolParameters,
|
||||||
});
|
// });
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Face restoration (${facetoolType}) requested: ${JSON.stringify(
|
// message: `Face restoration (${facetoolType}) requested: ${JSON.stringify(
|
||||||
{
|
// {
|
||||||
file: imageToProcess.url,
|
// file: imageToProcess.url,
|
||||||
...facetoolParameters,
|
// ...facetoolParameters,
|
||||||
}
|
// }
|
||||||
)}`,
|
// )}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
emitDeleteImage: (imageToDelete: InvokeAI._Image) => {
|
// emitDeleteImage: (imageToDelete: InvokeAI._Image) => {
|
||||||
const { url, uuid, category, thumbnail } = imageToDelete;
|
// const { url, uuid, category, thumbnail } = imageToDelete;
|
||||||
dispatch(removeImage(imageToDelete));
|
// dispatch(removeImage(imageToDelete));
|
||||||
socketio.emit('deleteImage', url, thumbnail, uuid, category);
|
// socketio.emit('deleteImage', url, thumbnail, uuid, category);
|
||||||
},
|
// },
|
||||||
emitRequestImages: (category: GalleryCategory) => {
|
// emitRequestImages: (category: GalleryCategory) => {
|
||||||
const gallery: GalleryState = getState().gallery;
|
// const gallery: GalleryState = getState().gallery;
|
||||||
const { earliest_mtime } = gallery.categories[category];
|
// const { earliest_mtime } = gallery.categories[category];
|
||||||
socketio.emit('requestImages', category, earliest_mtime);
|
// socketio.emit('requestImages', category, earliest_mtime);
|
||||||
},
|
// },
|
||||||
emitRequestNewImages: (category: GalleryCategory) => {
|
// emitRequestNewImages: (category: GalleryCategory) => {
|
||||||
const gallery: GalleryState = getState().gallery;
|
// const gallery: GalleryState = getState().gallery;
|
||||||
const { latest_mtime } = gallery.categories[category];
|
// const { latest_mtime } = gallery.categories[category];
|
||||||
socketio.emit('requestLatestImages', category, latest_mtime);
|
// socketio.emit('requestLatestImages', category, latest_mtime);
|
||||||
},
|
// },
|
||||||
emitCancelProcessing: () => {
|
// emitCancelProcessing: () => {
|
||||||
socketio.emit('cancel');
|
// socketio.emit('cancel');
|
||||||
},
|
// },
|
||||||
emitRequestSystemConfig: () => {
|
// emitRequestSystemConfig: () => {
|
||||||
socketio.emit('requestSystemConfig');
|
// socketio.emit('requestSystemConfig');
|
||||||
},
|
// },
|
||||||
emitSearchForModels: (modelFolder: string) => {
|
// emitSearchForModels: (modelFolder: string) => {
|
||||||
socketio.emit('searchForModels', modelFolder);
|
// socketio.emit('searchForModels', modelFolder);
|
||||||
},
|
// },
|
||||||
emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => {
|
// emitAddNewModel: (modelConfig: InvokeAI.InvokeModelConfigProps) => {
|
||||||
socketio.emit('addNewModel', modelConfig);
|
// socketio.emit('addNewModel', modelConfig);
|
||||||
},
|
// },
|
||||||
emitDeleteModel: (modelName: string) => {
|
// emitDeleteModel: (modelName: string) => {
|
||||||
socketio.emit('deleteModel', modelName);
|
// socketio.emit('deleteModel', modelName);
|
||||||
},
|
// },
|
||||||
emitConvertToDiffusers: (
|
// emitConvertToDiffusers: (
|
||||||
modelToConvert: InvokeAI.InvokeModelConversionProps
|
// modelToConvert: InvokeAI.InvokeModelConversionProps
|
||||||
) => {
|
// ) => {
|
||||||
dispatch(modelConvertRequested());
|
// dispatch(modelConvertRequested());
|
||||||
socketio.emit('convertToDiffusers', modelToConvert);
|
// socketio.emit('convertToDiffusers', modelToConvert);
|
||||||
},
|
// },
|
||||||
emitMergeDiffusersModels: (
|
// emitMergeDiffusersModels: (
|
||||||
modelMergeInfo: InvokeAI.InvokeModelMergingProps
|
// modelMergeInfo: InvokeAI.InvokeModelMergingProps
|
||||||
) => {
|
// ) => {
|
||||||
dispatch(modelMergingRequested());
|
// dispatch(modelMergingRequested());
|
||||||
socketio.emit('mergeDiffusersModels', modelMergeInfo);
|
// socketio.emit('mergeDiffusersModels', modelMergeInfo);
|
||||||
},
|
// },
|
||||||
emitRequestModelChange: (modelName: string) => {
|
// emitRequestModelChange: (modelName: string) => {
|
||||||
dispatch(modelChangeRequested());
|
// dispatch(modelChangeRequested());
|
||||||
socketio.emit('requestModelChange', modelName);
|
// socketio.emit('requestModelChange', modelName);
|
||||||
},
|
// },
|
||||||
emitSaveStagingAreaImageToGallery: (url: string) => {
|
// emitSaveStagingAreaImageToGallery: (url: string) => {
|
||||||
socketio.emit('requestSaveStagingAreaImageToGallery', url);
|
// socketio.emit('requestSaveStagingAreaImageToGallery', url);
|
||||||
},
|
// },
|
||||||
emitRequestEmptyTempFolder: () => {
|
// emitRequestEmptyTempFolder: () => {
|
||||||
socketio.emit('requestEmptyTempFolder');
|
// socketio.emit('requestEmptyTempFolder');
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default makeSocketIOEmitters;
|
// export default makeSocketIOEmitters;
|
||||||
|
|
||||||
|
export default {};
|
||||||
|
@ -1,500 +1,502 @@
|
|||||||
import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
// import { AnyAction, Dispatch, MiddlewareAPI } from '@reduxjs/toolkit';
|
||||||
import dateFormat from 'dateformat';
|
// import dateFormat from 'dateformat';
|
||||||
import i18n from 'i18n';
|
// import i18n from 'i18n';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
// import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import * as InvokeAI from 'app/types/invokeai';
|
// import * as InvokeAI from 'app/types/invokeai';
|
||||||
|
|
||||||
import {
|
// import {
|
||||||
addToast,
|
// addToast,
|
||||||
errorOccurred,
|
// errorOccurred,
|
||||||
processingCanceled,
|
// processingCanceled,
|
||||||
setCurrentStatus,
|
// setCurrentStatus,
|
||||||
setFoundModels,
|
// setFoundModels,
|
||||||
setIsCancelable,
|
// setIsCancelable,
|
||||||
setIsConnected,
|
// setIsConnected,
|
||||||
setIsProcessing,
|
// setIsProcessing,
|
||||||
setModelList,
|
// setModelList,
|
||||||
setSearchFolder,
|
// setSearchFolder,
|
||||||
setSystemConfig,
|
// setSystemConfig,
|
||||||
setSystemStatus,
|
// setSystemStatus,
|
||||||
} from 'features/system/store/systemSlice';
|
// } from 'features/system/store/systemSlice';
|
||||||
|
|
||||||
import {
|
// import {
|
||||||
addGalleryImages,
|
// addGalleryImages,
|
||||||
addImage,
|
// addImage,
|
||||||
clearIntermediateImage,
|
// clearIntermediateImage,
|
||||||
GalleryState,
|
// GalleryState,
|
||||||
removeImage,
|
// removeImage,
|
||||||
setIntermediateImage,
|
// setIntermediateImage,
|
||||||
} from 'features/gallery/store/gallerySlice';
|
// } from 'features/gallery/store/gallerySlice';
|
||||||
|
|
||||||
import type { RootState } from 'app/store/store';
|
// import type { RootState } from 'app/store/store';
|
||||||
import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
// import { addImageToStagingArea } from 'features/canvas/store/canvasSlice';
|
||||||
import {
|
// import {
|
||||||
clearInitialImage,
|
// clearInitialImage,
|
||||||
initialImageSelected,
|
// initialImageSelected,
|
||||||
setInfillMethod,
|
// setInfillMethod,
|
||||||
// setInitialImage,
|
// // setInitialImage,
|
||||||
setMaskPath,
|
// setMaskPath,
|
||||||
} from 'features/parameters/store/generationSlice';
|
// } from 'features/parameters/store/generationSlice';
|
||||||
import { tabMap } from 'features/ui/store/tabMap';
|
// import { tabMap } from 'features/ui/store/tabMap';
|
||||||
import {
|
// import {
|
||||||
requestImages,
|
// requestImages,
|
||||||
requestNewImages,
|
// requestNewImages,
|
||||||
requestSystemConfig,
|
// requestSystemConfig,
|
||||||
} from './actions';
|
// } from './actions';
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Returns an object containing listener callbacks for socketio events.
|
// * Returns an object containing listener callbacks for socketio events.
|
||||||
* TODO: This file is large, but simple. Should it be split up further?
|
// * TODO: This file is large, but simple. Should it be split up further?
|
||||||
*/
|
// */
|
||||||
const makeSocketIOListeners = (
|
// const makeSocketIOListeners = (
|
||||||
store: MiddlewareAPI<Dispatch<AnyAction>, RootState>
|
// store: MiddlewareAPI<Dispatch<AnyAction>, RootState>
|
||||||
) => {
|
// ) => {
|
||||||
const { dispatch, getState } = store;
|
// const { dispatch, getState } = store;
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'connect' event.
|
// * Callback to run when we receive a 'connect' event.
|
||||||
*/
|
// */
|
||||||
onConnect: () => {
|
// onConnect: () => {
|
||||||
try {
|
// try {
|
||||||
dispatch(setIsConnected(true));
|
// dispatch(setIsConnected(true));
|
||||||
dispatch(setCurrentStatus(i18n.t('common.statusConnected')));
|
// dispatch(setCurrentStatus(i18n.t('common.statusConnected')));
|
||||||
dispatch(requestSystemConfig());
|
// dispatch(requestSystemConfig());
|
||||||
const gallery: GalleryState = getState().gallery;
|
// const gallery: GalleryState = getState().gallery;
|
||||||
|
|
||||||
if (gallery.categories.result.latest_mtime) {
|
// if (gallery.categories.result.latest_mtime) {
|
||||||
dispatch(requestNewImages('result'));
|
// dispatch(requestNewImages('result'));
|
||||||
} else {
|
// } else {
|
||||||
dispatch(requestImages('result'));
|
// dispatch(requestImages('result'));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (gallery.categories.user.latest_mtime) {
|
// if (gallery.categories.user.latest_mtime) {
|
||||||
dispatch(requestNewImages('user'));
|
// dispatch(requestNewImages('user'));
|
||||||
} else {
|
// } else {
|
||||||
dispatch(requestImages('user'));
|
// dispatch(requestImages('user'));
|
||||||
}
|
// }
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'disconnect' event.
|
// * Callback to run when we receive a 'disconnect' event.
|
||||||
*/
|
// */
|
||||||
onDisconnect: () => {
|
// onDisconnect: () => {
|
||||||
try {
|
// try {
|
||||||
dispatch(setIsConnected(false));
|
// dispatch(setIsConnected(false));
|
||||||
dispatch(setCurrentStatus(i18n.t('common.statusDisconnected')));
|
// dispatch(setCurrentStatus(i18n.t('common.statusDisconnected')));
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Disconnected from server`,
|
// message: `Disconnected from server`,
|
||||||
level: 'warning',
|
// level: 'warning',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'generationResult' event.
|
// * Callback to run when we receive a 'generationResult' event.
|
||||||
*/
|
// */
|
||||||
onGenerationResult: (data: InvokeAI.ImageResultResponse) => {
|
// onGenerationResult: (data: InvokeAI.ImageResultResponse) => {
|
||||||
try {
|
// try {
|
||||||
const state = getState();
|
// const state = getState();
|
||||||
const { activeTab } = state.ui;
|
// const { activeTab } = state.ui;
|
||||||
const { shouldLoopback } = state.postprocessing;
|
// const { shouldLoopback } = state.postprocessing;
|
||||||
const { boundingBox: _, generationMode, ...rest } = data;
|
// const { boundingBox: _, generationMode, ...rest } = data;
|
||||||
|
|
||||||
const newImage = {
|
// const newImage = {
|
||||||
uuid: uuidv4(),
|
// uuid: uuidv4(),
|
||||||
...rest,
|
// ...rest,
|
||||||
};
|
// };
|
||||||
|
|
||||||
if (['txt2img', 'img2img'].includes(generationMode)) {
|
// if (['txt2img', 'img2img'].includes(generationMode)) {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addImage({
|
// addImage({
|
||||||
category: 'result',
|
// category: 'result',
|
||||||
image: { ...newImage, category: 'result' },
|
// image: { ...newImage, category: 'result' },
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (generationMode === 'unifiedCanvas' && data.boundingBox) {
|
// if (generationMode === 'unifiedCanvas' && data.boundingBox) {
|
||||||
const { boundingBox } = data;
|
// const { boundingBox } = data;
|
||||||
dispatch(
|
// dispatch(
|
||||||
addImageToStagingArea({
|
// addImageToStagingArea({
|
||||||
image: { ...newImage, category: 'temp' },
|
// image: { ...newImage, category: 'temp' },
|
||||||
boundingBox,
|
// boundingBox,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (state.canvas.shouldAutoSave) {
|
// if (state.canvas.shouldAutoSave) {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addImage({
|
// addImage({
|
||||||
image: { ...newImage, category: 'result' },
|
// image: { ...newImage, category: 'result' },
|
||||||
category: 'result',
|
// category: 'result',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// TODO: fix
|
// // TODO: fix
|
||||||
// if (shouldLoopback) {
|
// // if (shouldLoopback) {
|
||||||
// const activeTabName = tabMap[activeTab];
|
// // const activeTabName = tabMap[activeTab];
|
||||||
// switch (activeTabName) {
|
// // switch (activeTabName) {
|
||||||
// case 'img2img': {
|
// // case 'img2img': {
|
||||||
// dispatch(initialImageSelected(newImage.uuid));
|
// // dispatch(initialImageSelected(newImage.uuid));
|
||||||
// // dispatch(setInitialImage(newImage));
|
// // // dispatch(setInitialImage(newImage));
|
||||||
// break;
|
// // break;
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
// }
|
// // }
|
||||||
|
|
||||||
dispatch(clearIntermediateImage());
|
// dispatch(clearIntermediateImage());
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Image generated: ${data.url}`,
|
// message: `Image generated: ${data.url}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'intermediateResult' event.
|
// * Callback to run when we receive a 'intermediateResult' event.
|
||||||
*/
|
// */
|
||||||
onIntermediateResult: (data: InvokeAI.ImageResultResponse) => {
|
// onIntermediateResult: (data: InvokeAI.ImageResultResponse) => {
|
||||||
try {
|
// try {
|
||||||
dispatch(
|
// dispatch(
|
||||||
setIntermediateImage({
|
// setIntermediateImage({
|
||||||
uuid: uuidv4(),
|
// uuid: uuidv4(),
|
||||||
...data,
|
// ...data,
|
||||||
category: 'result',
|
// category: 'result',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
if (!data.isBase64) {
|
// if (!data.isBase64) {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Intermediate image generated: ${data.url}`,
|
// message: `Intermediate image generated: ${data.url}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive an 'esrganResult' event.
|
// * Callback to run when we receive an 'esrganResult' event.
|
||||||
*/
|
// */
|
||||||
onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => {
|
// onPostprocessingResult: (data: InvokeAI.ImageResultResponse) => {
|
||||||
try {
|
// try {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addImage({
|
// addImage({
|
||||||
category: 'result',
|
// category: 'result',
|
||||||
image: {
|
// image: {
|
||||||
uuid: uuidv4(),
|
// uuid: uuidv4(),
|
||||||
...data,
|
// ...data,
|
||||||
category: 'result',
|
// category: 'result',
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Postprocessed: ${data.url}`,
|
// message: `Postprocessed: ${data.url}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'progressUpdate' event.
|
// * Callback to run when we receive a 'progressUpdate' event.
|
||||||
* TODO: Add additional progress phases
|
// * TODO: Add additional progress phases
|
||||||
*/
|
// */
|
||||||
onProgressUpdate: (data: InvokeAI.SystemStatus) => {
|
// onProgressUpdate: (data: InvokeAI.SystemStatus) => {
|
||||||
try {
|
// try {
|
||||||
dispatch(setIsProcessing(true));
|
// dispatch(setIsProcessing(true));
|
||||||
dispatch(setSystemStatus(data));
|
// dispatch(setSystemStatus(data));
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'progressUpdate' event.
|
// * Callback to run when we receive a 'progressUpdate' event.
|
||||||
*/
|
// */
|
||||||
onError: (data: InvokeAI.ErrorResponse) => {
|
// onError: (data: InvokeAI.ErrorResponse) => {
|
||||||
const { message, additionalData } = data;
|
// const { message, additionalData } = data;
|
||||||
|
|
||||||
if (additionalData) {
|
// if (additionalData) {
|
||||||
// TODO: handle more data than short message
|
// // TODO: handle more data than short message
|
||||||
}
|
// }
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Server error: ${message}`,
|
// message: `Server error: ${message}`,
|
||||||
level: 'error',
|
// level: 'error',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
dispatch(errorOccurred());
|
// dispatch(errorOccurred());
|
||||||
dispatch(clearIntermediateImage());
|
// dispatch(clearIntermediateImage());
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
console.error(e);
|
// console.error(e);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'galleryImages' event.
|
// * Callback to run when we receive a 'galleryImages' event.
|
||||||
*/
|
// */
|
||||||
onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => {
|
// onGalleryImages: (data: InvokeAI.GalleryImagesResponse) => {
|
||||||
const { images, areMoreImagesAvailable, category } = data;
|
// const { images, areMoreImagesAvailable, category } = data;
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* the logic here ideally would be in the reducer but we have a side effect:
|
// * the logic here ideally would be in the reducer but we have a side effect:
|
||||||
* generating a uuid. so the logic needs to be here, outside redux.
|
// * generating a uuid. so the logic needs to be here, outside redux.
|
||||||
*/
|
// */
|
||||||
|
|
||||||
// Generate a UUID for each image
|
// // Generate a UUID for each image
|
||||||
const preparedImages = images.map((image): InvokeAI._Image => {
|
// const preparedImages = images.map((image): InvokeAI._Image => {
|
||||||
return {
|
// return {
|
||||||
uuid: uuidv4(),
|
// uuid: uuidv4(),
|
||||||
...image,
|
// ...image,
|
||||||
};
|
// };
|
||||||
});
|
// });
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addGalleryImages({
|
// addGalleryImages({
|
||||||
images: preparedImages,
|
// images: preparedImages,
|
||||||
areMoreImagesAvailable,
|
// areMoreImagesAvailable,
|
||||||
category,
|
// category,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Loaded ${images.length} images`,
|
// message: `Loaded ${images.length} images`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'processingCanceled' event.
|
// * Callback to run when we receive a 'processingCanceled' event.
|
||||||
*/
|
// */
|
||||||
onProcessingCanceled: () => {
|
// onProcessingCanceled: () => {
|
||||||
dispatch(processingCanceled());
|
// dispatch(processingCanceled());
|
||||||
|
|
||||||
const { intermediateImage } = getState().gallery;
|
// const { intermediateImage } = getState().gallery;
|
||||||
|
|
||||||
if (intermediateImage) {
|
// if (intermediateImage) {
|
||||||
if (!intermediateImage.isBase64) {
|
// if (!intermediateImage.isBase64) {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addImage({
|
// addImage({
|
||||||
category: 'result',
|
// category: 'result',
|
||||||
image: intermediateImage,
|
// image: intermediateImage,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Intermediate image saved: ${intermediateImage.url}`,
|
// message: `Intermediate image saved: ${intermediateImage.url}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
dispatch(clearIntermediateImage());
|
// dispatch(clearIntermediateImage());
|
||||||
}
|
// }
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Processing canceled`,
|
// message: `Processing canceled`,
|
||||||
level: 'warning',
|
// level: 'warning',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
/**
|
// /**
|
||||||
* Callback to run when we receive a 'imageDeleted' event.
|
// * Callback to run when we receive a 'imageDeleted' event.
|
||||||
*/
|
// */
|
||||||
onImageDeleted: (data: InvokeAI.ImageDeletedResponse) => {
|
// onImageDeleted: (data: InvokeAI.ImageDeletedResponse) => {
|
||||||
const { url } = data;
|
// const { url } = data;
|
||||||
|
|
||||||
// remove image from gallery
|
// // remove image from gallery
|
||||||
dispatch(removeImage(data));
|
// dispatch(removeImage(data));
|
||||||
|
|
||||||
// remove references to image in options
|
// // remove references to image in options
|
||||||
const {
|
// const {
|
||||||
generation: { initialImage, maskPath },
|
// generation: { initialImage, maskPath },
|
||||||
} = getState();
|
// } = getState();
|
||||||
|
|
||||||
if (
|
// if (
|
||||||
initialImage === url ||
|
// initialImage === url ||
|
||||||
(initialImage as InvokeAI._Image)?.url === url
|
// (initialImage as InvokeAI._Image)?.url === url
|
||||||
) {
|
// ) {
|
||||||
dispatch(clearInitialImage());
|
// dispatch(clearInitialImage());
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (maskPath === url) {
|
// if (maskPath === url) {
|
||||||
dispatch(setMaskPath(''));
|
// dispatch(setMaskPath(''));
|
||||||
}
|
// }
|
||||||
|
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Image deleted: ${url}`,
|
// message: `Image deleted: ${url}`,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onSystemConfig: (data: InvokeAI.SystemConfig) => {
|
// onSystemConfig: (data: InvokeAI.SystemConfig) => {
|
||||||
dispatch(setSystemConfig(data));
|
// dispatch(setSystemConfig(data));
|
||||||
if (!data.infill_methods.includes('patchmatch')) {
|
// if (!data.infill_methods.includes('patchmatch')) {
|
||||||
dispatch(setInfillMethod(data.infill_methods[0]));
|
// dispatch(setInfillMethod(data.infill_methods[0]));
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
onFoundModels: (data: InvokeAI.FoundModelResponse) => {
|
// onFoundModels: (data: InvokeAI.FoundModelResponse) => {
|
||||||
const { search_folder, found_models } = data;
|
// const { search_folder, found_models } = data;
|
||||||
dispatch(setSearchFolder(search_folder));
|
// dispatch(setSearchFolder(search_folder));
|
||||||
dispatch(setFoundModels(found_models));
|
// dispatch(setFoundModels(found_models));
|
||||||
},
|
// },
|
||||||
onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => {
|
// onNewModelAdded: (data: InvokeAI.ModelAddedResponse) => {
|
||||||
const { new_model_name, model_list, update } = data;
|
// const { new_model_name, model_list, update } = data;
|
||||||
dispatch(setModelList(model_list));
|
// dispatch(setModelList(model_list));
|
||||||
dispatch(setIsProcessing(false));
|
// dispatch(setIsProcessing(false));
|
||||||
dispatch(setCurrentStatus(i18n.t('modelManager.modelAdded')));
|
// dispatch(setCurrentStatus(i18n.t('modelManager.modelAdded')));
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Model Added: ${new_model_name}`,
|
// message: `Model Added: ${new_model_name}`,
|
||||||
level: 'info',
|
// level: 'info',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
dispatch(
|
// dispatch(
|
||||||
addToast({
|
// addToast({
|
||||||
title: !update
|
// title: !update
|
||||||
? `${i18n.t('modelManager.modelAdded')}: ${new_model_name}`
|
// ? `${i18n.t('modelManager.modelAdded')}: ${new_model_name}`
|
||||||
: `${i18n.t('modelManager.modelUpdated')}: ${new_model_name}`,
|
// : `${i18n.t('modelManager.modelUpdated')}: ${new_model_name}`,
|
||||||
status: 'success',
|
// status: 'success',
|
||||||
duration: 2500,
|
// duration: 2500,
|
||||||
isClosable: true,
|
// isClosable: true,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => {
|
// onModelDeleted: (data: InvokeAI.ModelDeletedResponse) => {
|
||||||
const { deleted_model_name, model_list } = data;
|
// const { deleted_model_name, model_list } = data;
|
||||||
dispatch(setModelList(model_list));
|
// dispatch(setModelList(model_list));
|
||||||
dispatch(setIsProcessing(false));
|
// dispatch(setIsProcessing(false));
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `${i18n.t(
|
// message: `${i18n.t(
|
||||||
'modelManager.modelAdded'
|
// 'modelManager.modelAdded'
|
||||||
)}: ${deleted_model_name}`,
|
// )}: ${deleted_model_name}`,
|
||||||
level: 'info',
|
// level: 'info',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
dispatch(
|
// dispatch(
|
||||||
addToast({
|
// addToast({
|
||||||
title: `${i18n.t(
|
// title: `${i18n.t(
|
||||||
'modelManager.modelEntryDeleted'
|
// 'modelManager.modelEntryDeleted'
|
||||||
)}: ${deleted_model_name}`,
|
// )}: ${deleted_model_name}`,
|
||||||
status: 'success',
|
// status: 'success',
|
||||||
duration: 2500,
|
// duration: 2500,
|
||||||
isClosable: true,
|
// isClosable: true,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onModelConverted: (data: InvokeAI.ModelConvertedResponse) => {
|
// onModelConverted: (data: InvokeAI.ModelConvertedResponse) => {
|
||||||
const { converted_model_name, model_list } = data;
|
// const { converted_model_name, model_list } = data;
|
||||||
dispatch(setModelList(model_list));
|
// dispatch(setModelList(model_list));
|
||||||
dispatch(setCurrentStatus(i18n.t('common.statusModelConverted')));
|
// dispatch(setCurrentStatus(i18n.t('common.statusModelConverted')));
|
||||||
dispatch(setIsProcessing(false));
|
// dispatch(setIsProcessing(false));
|
||||||
dispatch(setIsCancelable(true));
|
// dispatch(setIsCancelable(true));
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Model converted: ${converted_model_name}`,
|
// message: `Model converted: ${converted_model_name}`,
|
||||||
level: 'info',
|
// level: 'info',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
dispatch(
|
// dispatch(
|
||||||
addToast({
|
// addToast({
|
||||||
title: `${i18n.t(
|
// title: `${i18n.t(
|
||||||
'modelManager.modelConverted'
|
// 'modelManager.modelConverted'
|
||||||
)}: ${converted_model_name}`,
|
// )}: ${converted_model_name}`,
|
||||||
status: 'success',
|
// status: 'success',
|
||||||
duration: 2500,
|
// duration: 2500,
|
||||||
isClosable: true,
|
// isClosable: true,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onModelsMerged: (data: InvokeAI.ModelsMergedResponse) => {
|
// onModelsMerged: (data: InvokeAI.ModelsMergedResponse) => {
|
||||||
const { merged_models, merged_model_name, model_list } = data;
|
// const { merged_models, merged_model_name, model_list } = data;
|
||||||
dispatch(setModelList(model_list));
|
// dispatch(setModelList(model_list));
|
||||||
dispatch(setCurrentStatus(i18n.t('common.statusMergedModels')));
|
// dispatch(setCurrentStatus(i18n.t('common.statusMergedModels')));
|
||||||
dispatch(setIsProcessing(false));
|
// dispatch(setIsProcessing(false));
|
||||||
dispatch(setIsCancelable(true));
|
// dispatch(setIsCancelable(true));
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Models merged: ${merged_models}`,
|
// message: `Models merged: ${merged_models}`,
|
||||||
level: 'info',
|
// level: 'info',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
dispatch(
|
// dispatch(
|
||||||
addToast({
|
// addToast({
|
||||||
title: `${i18n.t('modelManager.modelsMerged')}: ${merged_model_name}`,
|
// title: `${i18n.t('modelManager.modelsMerged')}: ${merged_model_name}`,
|
||||||
status: 'success',
|
// status: 'success',
|
||||||
duration: 2500,
|
// duration: 2500,
|
||||||
isClosable: true,
|
// isClosable: true,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onModelChanged: (data: InvokeAI.ModelChangeResponse) => {
|
// onModelChanged: (data: InvokeAI.ModelChangeResponse) => {
|
||||||
const { model_name, model_list } = data;
|
// const { model_name, model_list } = data;
|
||||||
dispatch(setModelList(model_list));
|
// dispatch(setModelList(model_list));
|
||||||
dispatch(setCurrentStatus(i18n.t('common.statusModelChanged')));
|
// dispatch(setCurrentStatus(i18n.t('common.statusModelChanged')));
|
||||||
dispatch(setIsProcessing(false));
|
// dispatch(setIsProcessing(false));
|
||||||
dispatch(setIsCancelable(true));
|
// dispatch(setIsCancelable(true));
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Model changed: ${model_name}`,
|
// message: `Model changed: ${model_name}`,
|
||||||
level: 'info',
|
// level: 'info',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onModelChangeFailed: (data: InvokeAI.ModelChangeResponse) => {
|
// onModelChangeFailed: (data: InvokeAI.ModelChangeResponse) => {
|
||||||
const { model_name, model_list } = data;
|
// const { model_name, model_list } = data;
|
||||||
dispatch(setModelList(model_list));
|
// dispatch(setModelList(model_list));
|
||||||
dispatch(setIsProcessing(false));
|
// dispatch(setIsProcessing(false));
|
||||||
dispatch(setIsCancelable(true));
|
// dispatch(setIsCancelable(true));
|
||||||
dispatch(errorOccurred());
|
// dispatch(errorOccurred());
|
||||||
dispatch(
|
// dispatch(
|
||||||
addLogEntry({
|
// addLogEntry({
|
||||||
timestamp: dateFormat(new Date(), 'isoDateTime'),
|
// timestamp: dateFormat(new Date(), 'isoDateTime'),
|
||||||
message: `Model change failed: ${model_name}`,
|
// message: `Model change failed: ${model_name}`,
|
||||||
level: 'error',
|
// level: 'error',
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
onTempFolderEmptied: () => {
|
// onTempFolderEmptied: () => {
|
||||||
dispatch(
|
// dispatch(
|
||||||
addToast({
|
// addToast({
|
||||||
title: i18n.t('toast.tempFoldersEmptied'),
|
// title: i18n.t('toast.tempFoldersEmptied'),
|
||||||
status: 'success',
|
// status: 'success',
|
||||||
duration: 2500,
|
// duration: 2500,
|
||||||
isClosable: true,
|
// isClosable: true,
|
||||||
})
|
// })
|
||||||
);
|
// );
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default makeSocketIOListeners;
|
// export default makeSocketIOListeners;
|
||||||
|
|
||||||
|
export default {};
|
||||||
|
@ -1,246 +1,248 @@
|
|||||||
import { Middleware } from '@reduxjs/toolkit';
|
// import { Middleware } from '@reduxjs/toolkit';
|
||||||
import { io } from 'socket.io-client';
|
// import { io } from 'socket.io-client';
|
||||||
|
|
||||||
import makeSocketIOEmitters from './emitters';
|
// import makeSocketIOEmitters from './emitters';
|
||||||
import makeSocketIOListeners from './listeners';
|
// import makeSocketIOListeners from './listeners';
|
||||||
|
|
||||||
import * as InvokeAI from 'app/types/invokeai';
|
// import * as InvokeAI from 'app/types/invokeai';
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Creates a socketio middleware to handle communication with server.
|
// * Creates a socketio middleware to handle communication with server.
|
||||||
*
|
// *
|
||||||
* Special `socketio/actionName` actions are created in actions.ts and
|
// * Special `socketio/actionName` actions are created in actions.ts and
|
||||||
* exported for use by the application, which treats them like any old
|
// * exported for use by the application, which treats them like any old
|
||||||
* action, using `dispatch` to dispatch them.
|
// * action, using `dispatch` to dispatch them.
|
||||||
*
|
// *
|
||||||
* These actions are intercepted here, where `socketio.emit()` calls are
|
// * These actions are intercepted here, where `socketio.emit()` calls are
|
||||||
* made on their behalf - see `emitters.ts`. The emitter functions
|
// * made on their behalf - see `emitters.ts`. The emitter functions
|
||||||
* are the outbound communication to the server.
|
// * are the outbound communication to the server.
|
||||||
*
|
// *
|
||||||
* Listeners are also established here - see `listeners.ts`. The listener
|
// * Listeners are also established here - see `listeners.ts`. The listener
|
||||||
* functions receive communication from the server and usually dispatch
|
// * functions receive communication from the server and usually dispatch
|
||||||
* some new action to handle whatever data was sent from the server.
|
// * some new action to handle whatever data was sent from the server.
|
||||||
*/
|
// */
|
||||||
export const socketioMiddleware = () => {
|
// export const socketioMiddleware = () => {
|
||||||
const { origin } = new URL(window.location.href);
|
// const { origin } = new URL(window.location.href);
|
||||||
|
|
||||||
const socketio = io(origin, {
|
// const socketio = io(origin, {
|
||||||
timeout: 60000,
|
// timeout: 60000,
|
||||||
path: `${window.location.pathname}socket.io`,
|
// path: `${window.location.pathname}socket.io`,
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.disconnect();
|
// socketio.disconnect();
|
||||||
|
|
||||||
let areListenersSet = false;
|
// let areListenersSet = false;
|
||||||
|
|
||||||
const middleware: Middleware = (store) => (next) => (action) => {
|
// const middleware: Middleware = (store) => (next) => (action) => {
|
||||||
const {
|
// const {
|
||||||
onConnect,
|
// onConnect,
|
||||||
onDisconnect,
|
// onDisconnect,
|
||||||
onError,
|
// onError,
|
||||||
onPostprocessingResult,
|
// onPostprocessingResult,
|
||||||
onGenerationResult,
|
// onGenerationResult,
|
||||||
onIntermediateResult,
|
// onIntermediateResult,
|
||||||
onProgressUpdate,
|
// onProgressUpdate,
|
||||||
onGalleryImages,
|
// onGalleryImages,
|
||||||
onProcessingCanceled,
|
// onProcessingCanceled,
|
||||||
onImageDeleted,
|
// onImageDeleted,
|
||||||
onSystemConfig,
|
// onSystemConfig,
|
||||||
onModelChanged,
|
// onModelChanged,
|
||||||
onFoundModels,
|
// onFoundModels,
|
||||||
onNewModelAdded,
|
// onNewModelAdded,
|
||||||
onModelDeleted,
|
// onModelDeleted,
|
||||||
onModelConverted,
|
// onModelConverted,
|
||||||
onModelsMerged,
|
// onModelsMerged,
|
||||||
onModelChangeFailed,
|
// onModelChangeFailed,
|
||||||
onTempFolderEmptied,
|
// onTempFolderEmptied,
|
||||||
} = makeSocketIOListeners(store);
|
// } = makeSocketIOListeners(store);
|
||||||
|
|
||||||
const {
|
// const {
|
||||||
emitGenerateImage,
|
// emitGenerateImage,
|
||||||
emitRunESRGAN,
|
// emitRunESRGAN,
|
||||||
emitRunFacetool,
|
// emitRunFacetool,
|
||||||
emitDeleteImage,
|
// emitDeleteImage,
|
||||||
emitRequestImages,
|
// emitRequestImages,
|
||||||
emitRequestNewImages,
|
// emitRequestNewImages,
|
||||||
emitCancelProcessing,
|
// emitCancelProcessing,
|
||||||
emitRequestSystemConfig,
|
// emitRequestSystemConfig,
|
||||||
emitSearchForModels,
|
// emitSearchForModels,
|
||||||
emitAddNewModel,
|
// emitAddNewModel,
|
||||||
emitDeleteModel,
|
// emitDeleteModel,
|
||||||
emitConvertToDiffusers,
|
// emitConvertToDiffusers,
|
||||||
emitMergeDiffusersModels,
|
// emitMergeDiffusersModels,
|
||||||
emitRequestModelChange,
|
// emitRequestModelChange,
|
||||||
emitSaveStagingAreaImageToGallery,
|
// emitSaveStagingAreaImageToGallery,
|
||||||
emitRequestEmptyTempFolder,
|
// emitRequestEmptyTempFolder,
|
||||||
} = makeSocketIOEmitters(store, socketio);
|
// } = makeSocketIOEmitters(store, socketio);
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* If this is the first time the middleware has been called (e.g. during store setup),
|
// * If this is the first time the middleware has been called (e.g. during store setup),
|
||||||
* initialize all our socket.io listeners.
|
// * initialize all our socket.io listeners.
|
||||||
*/
|
// */
|
||||||
if (!areListenersSet) {
|
// if (!areListenersSet) {
|
||||||
socketio.on('connect', () => onConnect());
|
// socketio.on('connect', () => onConnect());
|
||||||
|
|
||||||
socketio.on('disconnect', () => onDisconnect());
|
// socketio.on('disconnect', () => onDisconnect());
|
||||||
|
|
||||||
socketio.on('error', (data: InvokeAI.ErrorResponse) => onError(data));
|
// socketio.on('error', (data: InvokeAI.ErrorResponse) => onError(data));
|
||||||
|
|
||||||
socketio.on('generationResult', (data: InvokeAI.ImageResultResponse) =>
|
// socketio.on('generationResult', (data: InvokeAI.ImageResultResponse) =>
|
||||||
onGenerationResult(data)
|
// onGenerationResult(data)
|
||||||
);
|
// );
|
||||||
|
|
||||||
socketio.on(
|
// socketio.on(
|
||||||
'postprocessingResult',
|
// 'postprocessingResult',
|
||||||
(data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data)
|
// (data: InvokeAI.ImageResultResponse) => onPostprocessingResult(data)
|
||||||
);
|
// );
|
||||||
|
|
||||||
socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) =>
|
// socketio.on('intermediateResult', (data: InvokeAI.ImageResultResponse) =>
|
||||||
onIntermediateResult(data)
|
// onIntermediateResult(data)
|
||||||
);
|
// );
|
||||||
|
|
||||||
socketio.on('progressUpdate', (data: InvokeAI.SystemStatus) =>
|
// socketio.on('progressUpdate', (data: InvokeAI.SystemStatus) =>
|
||||||
onProgressUpdate(data)
|
// onProgressUpdate(data)
|
||||||
);
|
// );
|
||||||
|
|
||||||
socketio.on('galleryImages', (data: InvokeAI.GalleryImagesResponse) =>
|
// socketio.on('galleryImages', (data: InvokeAI.GalleryImagesResponse) =>
|
||||||
onGalleryImages(data)
|
// onGalleryImages(data)
|
||||||
);
|
// );
|
||||||
|
|
||||||
socketio.on('processingCanceled', () => {
|
// socketio.on('processingCanceled', () => {
|
||||||
onProcessingCanceled();
|
// onProcessingCanceled();
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('imageDeleted', (data: InvokeAI.ImageDeletedResponse) => {
|
// socketio.on('imageDeleted', (data: InvokeAI.ImageDeletedResponse) => {
|
||||||
onImageDeleted(data);
|
// onImageDeleted(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => {
|
// socketio.on('systemConfig', (data: InvokeAI.SystemConfig) => {
|
||||||
onSystemConfig(data);
|
// onSystemConfig(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => {
|
// socketio.on('foundModels', (data: InvokeAI.FoundModelResponse) => {
|
||||||
onFoundModels(data);
|
// onFoundModels(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => {
|
// socketio.on('newModelAdded', (data: InvokeAI.ModelAddedResponse) => {
|
||||||
onNewModelAdded(data);
|
// onNewModelAdded(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => {
|
// socketio.on('modelDeleted', (data: InvokeAI.ModelDeletedResponse) => {
|
||||||
onModelDeleted(data);
|
// onModelDeleted(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('modelConverted', (data: InvokeAI.ModelConvertedResponse) => {
|
// socketio.on('modelConverted', (data: InvokeAI.ModelConvertedResponse) => {
|
||||||
onModelConverted(data);
|
// onModelConverted(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('modelsMerged', (data: InvokeAI.ModelsMergedResponse) => {
|
// socketio.on('modelsMerged', (data: InvokeAI.ModelsMergedResponse) => {
|
||||||
onModelsMerged(data);
|
// onModelsMerged(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => {
|
// socketio.on('modelChanged', (data: InvokeAI.ModelChangeResponse) => {
|
||||||
onModelChanged(data);
|
// onModelChanged(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('modelChangeFailed', (data: InvokeAI.ModelChangeResponse) => {
|
// socketio.on('modelChangeFailed', (data: InvokeAI.ModelChangeResponse) => {
|
||||||
onModelChangeFailed(data);
|
// onModelChangeFailed(data);
|
||||||
});
|
// });
|
||||||
|
|
||||||
socketio.on('tempFolderEmptied', () => {
|
// socketio.on('tempFolderEmptied', () => {
|
||||||
onTempFolderEmptied();
|
// onTempFolderEmptied();
|
||||||
});
|
// });
|
||||||
|
|
||||||
areListenersSet = true;
|
// areListenersSet = true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Handle redux actions caught by middleware.
|
// * Handle redux actions caught by middleware.
|
||||||
*/
|
// */
|
||||||
switch (action.type) {
|
// switch (action.type) {
|
||||||
case 'socketio/generateImage': {
|
// case 'socketio/generateImage': {
|
||||||
emitGenerateImage(action.payload);
|
// emitGenerateImage(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/runESRGAN': {
|
// case 'socketio/runESRGAN': {
|
||||||
emitRunESRGAN(action.payload);
|
// emitRunESRGAN(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/runFacetool': {
|
// case 'socketio/runFacetool': {
|
||||||
emitRunFacetool(action.payload);
|
// emitRunFacetool(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/deleteImage': {
|
// case 'socketio/deleteImage': {
|
||||||
emitDeleteImage(action.payload);
|
// emitDeleteImage(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/requestImages': {
|
// case 'socketio/requestImages': {
|
||||||
emitRequestImages(action.payload);
|
// emitRequestImages(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/requestNewImages': {
|
// case 'socketio/requestNewImages': {
|
||||||
emitRequestNewImages(action.payload);
|
// emitRequestNewImages(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/cancelProcessing': {
|
// case 'socketio/cancelProcessing': {
|
||||||
emitCancelProcessing();
|
// emitCancelProcessing();
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/requestSystemConfig': {
|
// case 'socketio/requestSystemConfig': {
|
||||||
emitRequestSystemConfig();
|
// emitRequestSystemConfig();
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/searchForModels': {
|
// case 'socketio/searchForModels': {
|
||||||
emitSearchForModels(action.payload);
|
// emitSearchForModels(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/addNewModel': {
|
// case 'socketio/addNewModel': {
|
||||||
emitAddNewModel(action.payload);
|
// emitAddNewModel(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/deleteModel': {
|
// case 'socketio/deleteModel': {
|
||||||
emitDeleteModel(action.payload);
|
// emitDeleteModel(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/convertToDiffusers': {
|
// case 'socketio/convertToDiffusers': {
|
||||||
emitConvertToDiffusers(action.payload);
|
// emitConvertToDiffusers(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/mergeDiffusersModels': {
|
// case 'socketio/mergeDiffusersModels': {
|
||||||
emitMergeDiffusersModels(action.payload);
|
// emitMergeDiffusersModels(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/requestModelChange': {
|
// case 'socketio/requestModelChange': {
|
||||||
emitRequestModelChange(action.payload);
|
// emitRequestModelChange(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/saveStagingAreaImageToGallery': {
|
// case 'socketio/saveStagingAreaImageToGallery': {
|
||||||
emitSaveStagingAreaImageToGallery(action.payload);
|
// emitSaveStagingAreaImageToGallery(action.payload);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case 'socketio/requestEmptyTempFolder': {
|
// case 'socketio/requestEmptyTempFolder': {
|
||||||
emitRequestEmptyTempFolder();
|
// emitRequestEmptyTempFolder();
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
next(action);
|
// next(action);
|
||||||
};
|
// };
|
||||||
|
|
||||||
return middleware;
|
// return middleware;
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
export default {};
|
||||||
|
@ -19,7 +19,6 @@ import hotkeysReducer from 'features/ui/store/hotkeysSlice';
|
|||||||
import modelsReducer from 'features/system/store/modelSlice';
|
import modelsReducer from 'features/system/store/modelSlice';
|
||||||
import nodesReducer from 'features/nodes/store/nodesSlice';
|
import nodesReducer from 'features/nodes/store/nodesSlice';
|
||||||
|
|
||||||
import { socketioMiddleware } from '../socketio/middleware';
|
|
||||||
import { socketMiddleware } from 'services/events/middleware';
|
import { socketMiddleware } from 'services/events/middleware';
|
||||||
import { canvasDenylist } from 'features/canvas/store/canvasPersistDenylist';
|
import { canvasDenylist } from 'features/canvas/store/canvasPersistDenylist';
|
||||||
import { galleryDenylist } from 'features/gallery/store/galleryPersistDenylist';
|
import { galleryDenylist } from 'features/gallery/store/galleryPersistDenylist';
|
||||||
@ -87,13 +86,13 @@ const rootPersistConfig = getPersistConfig({
|
|||||||
const persistedReducer = persistReducer(rootPersistConfig, rootReducer);
|
const persistedReducer = persistReducer(rootPersistConfig, rootReducer);
|
||||||
|
|
||||||
// TODO: rip the old middleware out when nodes is complete
|
// TODO: rip the old middleware out when nodes is complete
|
||||||
export function buildMiddleware() {
|
// export function buildMiddleware() {
|
||||||
if (import.meta.env.MODE === 'nodes' || import.meta.env.MODE === 'package') {
|
// if (import.meta.env.MODE === 'nodes' || import.meta.env.MODE === 'package') {
|
||||||
return socketMiddleware();
|
// return socketMiddleware();
|
||||||
} else {
|
// } else {
|
||||||
return socketioMiddleware();
|
// return socketioMiddleware();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: persistedReducer,
|
reducer: persistedReducer,
|
||||||
|
@ -111,9 +111,9 @@ export type FacetoolMetadata = CommonPostProcessedImageMetadata & {
|
|||||||
export type PostProcessedImageMetadata = ESRGANMetadata | FacetoolMetadata;
|
export type PostProcessedImageMetadata = ESRGANMetadata | FacetoolMetadata;
|
||||||
|
|
||||||
// Metadata includes the system config and image metadata.
|
// Metadata includes the system config and image metadata.
|
||||||
export type Metadata = SystemGenerationMetadata & {
|
// export type Metadata = SystemGenerationMetadata & {
|
||||||
image: GeneratedImageMetadata | PostProcessedImageMetadata;
|
// image: GeneratedImageMetadata | PostProcessedImageMetadata;
|
||||||
};
|
// };
|
||||||
|
|
||||||
// An Image has a UUID, url, modified timestamp, width, height and maybe metadata
|
// An Image has a UUID, url, modified timestamp, width, height and maybe metadata
|
||||||
export type _Image = {
|
export type _Image = {
|
||||||
@ -150,31 +150,31 @@ export type GalleryImages = {
|
|||||||
* Types related to the system status.
|
* Types related to the system status.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This represents the processing status of the backend.
|
// // This represents the processing status of the backend.
|
||||||
export type SystemStatus = {
|
// export type SystemStatus = {
|
||||||
isProcessing: boolean;
|
// isProcessing: boolean;
|
||||||
currentStep: number;
|
// currentStep: number;
|
||||||
totalSteps: number;
|
// totalSteps: number;
|
||||||
currentIteration: number;
|
// currentIteration: number;
|
||||||
totalIterations: number;
|
// totalIterations: number;
|
||||||
currentStatus: string;
|
// currentStatus: string;
|
||||||
currentStatusHasSteps: boolean;
|
// currentStatusHasSteps: boolean;
|
||||||
hasError: boolean;
|
// hasError: boolean;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export type SystemGenerationMetadata = {
|
// export type SystemGenerationMetadata = {
|
||||||
model: string;
|
// model: string;
|
||||||
model_weights?: string;
|
// model_weights?: string;
|
||||||
model_id?: string;
|
// model_id?: string;
|
||||||
model_hash: string;
|
// model_hash: string;
|
||||||
app_id: string;
|
// app_id: string;
|
||||||
app_version: string;
|
// app_version: string;
|
||||||
};
|
// };
|
||||||
|
|
||||||
export type SystemConfig = SystemGenerationMetadata & {
|
// export type SystemConfig = SystemGenerationMetadata & {
|
||||||
model_list: ModelList;
|
// model_list: ModelList;
|
||||||
infill_methods: string[];
|
// infill_methods: string[];
|
||||||
};
|
// };
|
||||||
|
|
||||||
export type ModelStatus = 'active' | 'cached' | 'not loaded';
|
export type ModelStatus = 'active' | 'cached' | 'not loaded';
|
||||||
|
|
||||||
@ -286,9 +286,9 @@ export type FoundModelResponse = {
|
|||||||
found_models: FoundModel[];
|
found_models: FoundModel[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SystemStatusResponse = SystemStatus;
|
// export type SystemStatusResponse = SystemStatus;
|
||||||
|
|
||||||
export type SystemConfigResponse = SystemConfig;
|
// export type SystemConfigResponse = SystemConfig;
|
||||||
|
|
||||||
export type ImageResultResponse = Omit<_Image, 'uuid'> & {
|
export type ImageResultResponse = Omit<_Image, 'uuid'> & {
|
||||||
boundingBox?: IRect;
|
boundingBox?: IRect;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ButtonGroup, Flex } from '@chakra-ui/react';
|
import { ButtonGroup, Flex } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { saveStagingAreaImageToGallery } from 'app/socketio/actions';
|
// import { saveStagingAreaImageToGallery } from 'app/socketio/actions';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { isEqual } from 'lodash-es';
|
import { get, isEqual, isNumber, isString } from 'lodash-es';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
@ -10,7 +10,7 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
useToast,
|
useToast,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
// import { runESRGAN, runFacetool } from 'app/socketio/actions';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
@ -68,6 +68,7 @@ import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvas
|
|||||||
import { useGetUrl } from 'common/util/getUrl';
|
import { useGetUrl } from 'common/util/getUrl';
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
import { imageDeleted } from 'services/thunks/image';
|
import { imageDeleted } from 'services/thunks/image';
|
||||||
|
import { useParameters } from 'features/parameters/hooks/useParameters';
|
||||||
|
|
||||||
const currentImageButtonsSelector = createSelector(
|
const currentImageButtonsSelector = createSelector(
|
||||||
[
|
[
|
||||||
@ -112,6 +113,8 @@ const currentImageButtonsSelector = createSelector(
|
|||||||
isLightboxOpen,
|
isLightboxOpen,
|
||||||
shouldHidePreview,
|
shouldHidePreview,
|
||||||
image,
|
image,
|
||||||
|
seed: image?.metadata?.invokeai?.node?.seed,
|
||||||
|
prompt: image?.metadata?.invokeai?.node?.prompt,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -161,16 +164,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
|
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const setBothPrompts = useSetBothPrompts();
|
|
||||||
|
|
||||||
const handleClickUseAsInitialImage = useCallback(() => {
|
const { recallPrompt, recallSeed, sendToImageToImage } = useParameters();
|
||||||
if (!image) return;
|
|
||||||
if (isLightboxOpen) dispatch(setIsLightboxOpen(false));
|
|
||||||
dispatch(initialImageSelected({ name: image.name, type: image.type }));
|
|
||||||
// dispatch(setInitialImage(currentImage));
|
|
||||||
|
|
||||||
// dispatch(setActiveTab('img2img'));
|
|
||||||
}, [dispatch, image, isLightboxOpen]);
|
|
||||||
|
|
||||||
const handleCopyImage = useCallback(async () => {
|
const handleCopyImage = useCallback(async () => {
|
||||||
if (!image?.url) {
|
if (!image?.url) {
|
||||||
@ -217,30 +212,6 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
});
|
});
|
||||||
}, [toast, shouldTransformUrls, getUrl, t, image]);
|
}, [toast, shouldTransformUrls, getUrl, t, image]);
|
||||||
|
|
||||||
useHotkeys(
|
|
||||||
'shift+i',
|
|
||||||
() => {
|
|
||||||
if (image) {
|
|
||||||
handleClickUseAsInitialImage();
|
|
||||||
toast({
|
|
||||||
title: t('toast.sentToImageToImage'),
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
title: t('toast.imageNotLoaded'),
|
|
||||||
description: t('toast.imageNotLoadedDesc'),
|
|
||||||
status: 'error',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[image]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handlePreviewVisibility = useCallback(() => {
|
const handlePreviewVisibility = useCallback(() => {
|
||||||
dispatch(setShouldHidePreview(!shouldHidePreview));
|
dispatch(setShouldHidePreview(!shouldHidePreview));
|
||||||
}, [dispatch, shouldHidePreview]);
|
}, [dispatch, shouldHidePreview]);
|
||||||
@ -259,7 +230,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
useHotkeys(
|
useHotkeys(
|
||||||
'a',
|
'a',
|
||||||
() => {
|
() => {
|
||||||
if (['txt2img', 'img2img'].includes(image?.metadata?.sd_metadata?.type)) {
|
const type = image?.metadata?.invokeai?.node?.types;
|
||||||
|
if (isString(type) && ['txt2img', 'img2img'].includes(type)) {
|
||||||
handleClickUseAllParameters();
|
handleClickUseAllParameters();
|
||||||
toast({
|
toast({
|
||||||
title: t('toast.parametersSet'),
|
title: t('toast.parametersSet'),
|
||||||
@ -280,63 +252,23 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
[image]
|
[image]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleClickUseSeed = () => {
|
const handleUseSeed = useCallback(() => {
|
||||||
image?.metadata && dispatch(setSeed(image.metadata.sd_metadata.seed));
|
recallSeed(image?.metadata?.invokeai?.node?.seed);
|
||||||
};
|
}, [image, recallSeed]);
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys('s', handleUseSeed, [image]);
|
||||||
's',
|
|
||||||
() => {
|
|
||||||
if (image?.metadata?.sd_metadata?.seed) {
|
|
||||||
handleClickUseSeed();
|
|
||||||
toast({
|
|
||||||
title: t('toast.seedSet'),
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
title: t('toast.seedNotSet'),
|
|
||||||
description: t('toast.seedNotSetDesc'),
|
|
||||||
status: 'error',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[image]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClickUsePrompt = useCallback(() => {
|
const handleUsePrompt = useCallback(() => {
|
||||||
if (image?.metadata?.sd_metadata?.prompt) {
|
recallPrompt(image?.metadata?.invokeai?.node?.prompt);
|
||||||
setBothPrompts(image?.metadata?.sd_metadata?.prompt);
|
}, [image, recallPrompt]);
|
||||||
}
|
|
||||||
}, [image?.metadata?.sd_metadata?.prompt, setBothPrompts]);
|
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys('p', handleUsePrompt, [image]);
|
||||||
'p',
|
|
||||||
() => {
|
const handleSendToImageToImage = useCallback(() => {
|
||||||
if (image?.metadata?.sd_metadata?.prompt) {
|
sendToImageToImage(image);
|
||||||
handleClickUsePrompt();
|
}, [image, sendToImageToImage]);
|
||||||
toast({
|
|
||||||
title: t('toast.promptSet'),
|
useHotkeys('shift+i', handleSendToImageToImage, [image]);
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
toast({
|
|
||||||
title: t('toast.promptNotSet'),
|
|
||||||
description: t('toast.promptNotSetDesc'),
|
|
||||||
status: 'error',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[image]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClickUpscale = useCallback(() => {
|
const handleClickUpscale = useCallback(() => {
|
||||||
// selectedImage && dispatch(runESRGAN(selectedImage));
|
// selectedImage && dispatch(runESRGAN(selectedImage));
|
||||||
@ -496,7 +428,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
>
|
>
|
||||||
<IAIButton
|
<IAIButton
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={handleClickUseAsInitialImage}
|
onClick={handleSendToImageToImage}
|
||||||
leftIcon={<FaShare />}
|
leftIcon={<FaShare />}
|
||||||
>
|
>
|
||||||
{t('parameters.sendToImg2Img')}
|
{t('parameters.sendToImg2Img')}
|
||||||
@ -570,8 +502,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
icon={<FaQuoteRight />}
|
icon={<FaQuoteRight />}
|
||||||
tooltip={`${t('parameters.usePrompt')} (P)`}
|
tooltip={`${t('parameters.usePrompt')} (P)`}
|
||||||
aria-label={`${t('parameters.usePrompt')} (P)`}
|
aria-label={`${t('parameters.usePrompt')} (P)`}
|
||||||
isDisabled={!image?.metadata?.sd_metadata?.prompt}
|
isDisabled={!image?.metadata?.invokeai?.node?.prompt}
|
||||||
onClick={handleClickUsePrompt}
|
onClick={handleUsePrompt}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IAIIconButton
|
<IAIIconButton
|
||||||
@ -579,7 +511,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
|
|||||||
tooltip={`${t('parameters.useSeed')} (S)`}
|
tooltip={`${t('parameters.useSeed')} (S)`}
|
||||||
aria-label={`${t('parameters.useSeed')} (S)`}
|
aria-label={`${t('parameters.useSeed')} (S)`}
|
||||||
isDisabled={!image?.metadata?.sd_metadata?.seed}
|
isDisabled={!image?.metadata?.sd_metadata?.seed}
|
||||||
onClick={handleClickUseSeed}
|
onClick={handleUseSeed}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<IAIIconButton
|
<IAIIconButton
|
||||||
|
@ -5,65 +5,37 @@ import {
|
|||||||
Image,
|
Image,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
MenuList,
|
MenuList,
|
||||||
Text,
|
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useTheme,
|
useTheme,
|
||||||
useToast,
|
useToast,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import {
|
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||||
imageSelected,
|
import { DragEvent, memo, useCallback, useState } from 'react';
|
||||||
setCurrentImage,
|
import { FaCheck, FaExpand, FaShare, FaTrash } from 'react-icons/fa';
|
||||||
} from 'features/gallery/store/gallerySlice';
|
|
||||||
import {
|
|
||||||
initialImageSelected,
|
|
||||||
setAllImageToImageParameters,
|
|
||||||
setAllParameters,
|
|
||||||
setSeed,
|
|
||||||
} from 'features/parameters/store/generationSlice';
|
|
||||||
import { DragEvent, memo, useState } from 'react';
|
|
||||||
import {
|
|
||||||
FaCheck,
|
|
||||||
FaExpand,
|
|
||||||
FaLink,
|
|
||||||
FaShare,
|
|
||||||
FaTrash,
|
|
||||||
FaTrashAlt,
|
|
||||||
} from 'react-icons/fa';
|
|
||||||
import DeleteImageModal from './DeleteImageModal';
|
import DeleteImageModal from './DeleteImageModal';
|
||||||
import { ContextMenu } from 'chakra-ui-contextmenu';
|
import { ContextMenu } from 'chakra-ui-contextmenu';
|
||||||
import * as InvokeAI from 'app/types/invokeai';
|
import * as InvokeAI from 'app/types/invokeai';
|
||||||
import {
|
import { resizeAndScaleCanvas } from 'features/canvas/store/canvasSlice';
|
||||||
resizeAndScaleCanvas,
|
|
||||||
setInitialCanvasImage,
|
|
||||||
} from 'features/canvas/store/canvasSlice';
|
|
||||||
import { gallerySelector } from 'features/gallery/store/gallerySelectors';
|
import { gallerySelector } from 'features/gallery/store/gallerySelectors';
|
||||||
import { setActiveTab } from 'features/ui/store/uiSlice';
|
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import useSetBothPrompts from 'features/parameters/hooks/usePrompt';
|
|
||||||
import { setIsLightboxOpen } from 'features/lightbox/store/lightboxSlice';
|
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
import IAIIconButton from 'common/components/IAIIconButton';
|
||||||
import { useGetUrl } from 'common/util/getUrl';
|
import { useGetUrl } from 'common/util/getUrl';
|
||||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
||||||
import { BiZoomIn } from 'react-icons/bi';
|
|
||||||
import { IoArrowUndoCircleOutline } from 'react-icons/io5';
|
import { IoArrowUndoCircleOutline } from 'react-icons/io5';
|
||||||
import { imageDeleted } from 'services/thunks/image';
|
import { imageDeleted } from 'services/thunks/image';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import { configSelector } from 'features/system/store/configSelectors';
|
|
||||||
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
import { lightboxSelector } from 'features/lightbox/store/lightboxSelectors';
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
|
import { useParameters } from 'features/parameters/hooks/useParameters';
|
||||||
|
|
||||||
export const selector = createSelector(
|
export const selector = createSelector(
|
||||||
[
|
[gallerySelector, systemSelector, lightboxSelector, activeTabNameSelector],
|
||||||
gallerySelector,
|
(gallery, system, lightbox, activeTabName) => {
|
||||||
systemSelector,
|
|
||||||
configSelector,
|
|
||||||
lightboxSelector,
|
|
||||||
activeTabNameSelector,
|
|
||||||
],
|
|
||||||
(gallery, system, config, lightbox, activeTabName) => {
|
|
||||||
const {
|
const {
|
||||||
galleryImageObjectFit,
|
galleryImageObjectFit,
|
||||||
galleryImageMinimumWidth,
|
galleryImageMinimumWidth,
|
||||||
@ -71,7 +43,6 @@ export const selector = createSelector(
|
|||||||
} = gallery;
|
} = gallery;
|
||||||
|
|
||||||
const { isLightboxOpen } = lightbox;
|
const { isLightboxOpen } = lightbox;
|
||||||
const { disabledFeatures } = config;
|
|
||||||
const { isConnected, isProcessing, shouldConfirmOnDelete } = system;
|
const { isConnected, isProcessing, shouldConfirmOnDelete } = system;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -82,7 +53,6 @@ export const selector = createSelector(
|
|||||||
shouldUseSingleGalleryColumn,
|
shouldUseSingleGalleryColumn,
|
||||||
activeTabName,
|
activeTabName,
|
||||||
isLightboxOpen,
|
isLightboxOpen,
|
||||||
disabledFeatures,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -113,14 +83,15 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
|||||||
galleryImageMinimumWidth,
|
galleryImageMinimumWidth,
|
||||||
canDeleteImage,
|
canDeleteImage,
|
||||||
shouldUseSingleGalleryColumn,
|
shouldUseSingleGalleryColumn,
|
||||||
disabledFeatures,
|
|
||||||
shouldConfirmOnDelete,
|
shouldConfirmOnDelete,
|
||||||
} = useAppSelector(selector);
|
} = useAppSelector(selector);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isOpen: isDeleteDialogOpen,
|
isOpen: isDeleteDialogOpen,
|
||||||
onOpen: onDeleteDialogOpen,
|
onOpen: onDeleteDialogOpen,
|
||||||
onClose: onDeleteDialogClose,
|
onClose: onDeleteDialogClose,
|
||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
|
||||||
const { image, isSelected } = props;
|
const { image, isSelected } = props;
|
||||||
const { url, thumbnail, name, metadata } = image;
|
const { url, thumbnail, name, metadata } = image;
|
||||||
const { getUrl } = useGetUrl();
|
const { getUrl } = useGetUrl();
|
||||||
@ -130,53 +101,62 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
|||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { direction } = useTheme();
|
const { direction } = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const setBothPrompts = useSetBothPrompts();
|
const { isFeatureEnabled: isLightboxEnabled } = useFeatureStatus('lightbox');
|
||||||
|
const { recallSeed, recallPrompt, sendToImageToImage, recallInitialImage } =
|
||||||
|
useParameters();
|
||||||
|
|
||||||
const handleMouseOver = () => setIsHovered(true);
|
const handleMouseOver = () => setIsHovered(true);
|
||||||
|
|
||||||
const handleMouseOut = () => setIsHovered(false);
|
const handleMouseOut = () => setIsHovered(false);
|
||||||
|
|
||||||
const handleInitiateDelete = () => {
|
// Immediately deletes an image
|
||||||
|
const handleDelete = useCallback(() => {
|
||||||
|
if (canDeleteImage && image) {
|
||||||
|
dispatch(imageDeleted({ imageType: image.type, imageName: image.name }));
|
||||||
|
}
|
||||||
|
}, [dispatch, image, canDeleteImage]);
|
||||||
|
|
||||||
|
// Opens the alert dialog to check if user is sure they want to delete
|
||||||
|
const handleInitiateDelete = useCallback(() => {
|
||||||
if (shouldConfirmOnDelete) {
|
if (shouldConfirmOnDelete) {
|
||||||
onDeleteDialogOpen();
|
onDeleteDialogOpen();
|
||||||
} else {
|
} else {
|
||||||
handleDelete();
|
handleDelete();
|
||||||
}
|
}
|
||||||
};
|
}, [handleDelete, onDeleteDialogOpen, shouldConfirmOnDelete]);
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleSelectImage = useCallback(() => {
|
||||||
if (canDeleteImage && image) {
|
dispatch(imageSelected(image.name));
|
||||||
dispatch(imageDeleted({ imageType: image.type, imageName: image.name }));
|
}, [image, dispatch]);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUsePrompt = () => {
|
const handleDragStart = useCallback(
|
||||||
if (typeof image.metadata?.invokeai?.node?.prompt === 'string') {
|
(e: DragEvent<HTMLDivElement>) => {
|
||||||
setBothPrompts(image.metadata?.invokeai?.node?.prompt);
|
e.dataTransfer.setData('invokeai/imageName', image.name);
|
||||||
}
|
e.dataTransfer.setData('invokeai/imageType', image.type);
|
||||||
toast({
|
e.dataTransfer.effectAllowed = 'move';
|
||||||
title: t('toast.promptSet'),
|
},
|
||||||
status: 'success',
|
[image]
|
||||||
duration: 2500,
|
);
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleUseSeed = () => {
|
// Recall parameters handlers
|
||||||
typeof image.metadata.invokeai?.node?.seed === 'number' &&
|
const handleRecallPrompt = useCallback(() => {
|
||||||
dispatch(setSeed(image.metadata.invokeai?.node?.seed));
|
recallPrompt(image.metadata?.invokeai?.node?.prompt);
|
||||||
toast({
|
}, [image, recallPrompt]);
|
||||||
title: t('toast.seedSet'),
|
|
||||||
status: 'success',
|
|
||||||
duration: 2500,
|
|
||||||
isClosable: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSendToImageToImage = () => {
|
const handleRecallSeed = useCallback(() => {
|
||||||
dispatch(initialImageSelected(image.name));
|
recallSeed(image.metadata.invokeai?.node?.seed);
|
||||||
};
|
}, [image, recallSeed]);
|
||||||
|
|
||||||
|
const handleSendToImageToImage = useCallback(() => {
|
||||||
|
sendToImageToImage(image);
|
||||||
|
}, [image, sendToImageToImage]);
|
||||||
|
|
||||||
|
const handleRecallInitialImage = useCallback(() => {
|
||||||
|
recallInitialImage(image.metadata.invokeai?.node?.image);
|
||||||
|
}, [image, recallInitialImage]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: the rest of these
|
||||||
|
*/
|
||||||
const handleSendToCanvas = () => {
|
const handleSendToCanvas = () => {
|
||||||
// dispatch(setInitialCanvasImage(image));
|
// dispatch(setInitialCanvasImage(image));
|
||||||
|
|
||||||
@ -205,41 +185,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
|||||||
// });
|
// });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUseInitialImage = async () => {
|
|
||||||
// if (metadata.invokeai?.node?.image?.init_image_path) {
|
|
||||||
// const response = await fetch(
|
|
||||||
// metadata.invokeai?.node?.image?.init_image_path
|
|
||||||
// );
|
|
||||||
// if (response.ok) {
|
|
||||||
// dispatch(setAllImageToImageParameters(metadata?.invokeai?.node));
|
|
||||||
// toast({
|
|
||||||
// title: t('toast.initialImageSet'),
|
|
||||||
// status: 'success',
|
|
||||||
// duration: 2500,
|
|
||||||
// isClosable: true,
|
|
||||||
// });
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// toast({
|
|
||||||
// title: t('toast.initialImageNotSet'),
|
|
||||||
// description: t('toast.initialImageNotSetDesc'),
|
|
||||||
// status: 'error',
|
|
||||||
// duration: 2500,
|
|
||||||
// isClosable: true,
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSelectImage = () => {
|
|
||||||
dispatch(imageSelected(image.name));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleDragStart = (e: DragEvent<HTMLDivElement>) => {
|
|
||||||
e.dataTransfer.setData('invokeai/imageName', image.name);
|
|
||||||
e.dataTransfer.setData('invokeai/imageType', image.type);
|
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLightBox = () => {
|
const handleLightBox = () => {
|
||||||
// dispatch(setCurrentImage(image));
|
// dispatch(setCurrentImage(image));
|
||||||
// dispatch(setIsLightboxOpen(true));
|
// dispatch(setIsLightboxOpen(true));
|
||||||
@ -254,21 +199,21 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
|||||||
<ContextMenu<HTMLDivElement>
|
<ContextMenu<HTMLDivElement>
|
||||||
menuProps={{ size: 'sm', isLazy: true }}
|
menuProps={{ size: 'sm', isLazy: true }}
|
||||||
renderMenu={() => (
|
renderMenu={() => (
|
||||||
<MenuList>
|
<MenuList sx={{ visibility: 'visible !important' }}>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<ExternalLinkIcon />}
|
icon={<ExternalLinkIcon />}
|
||||||
onClickCapture={handleOpenInNewTab}
|
onClickCapture={handleOpenInNewTab}
|
||||||
>
|
>
|
||||||
{t('common.openInNewTab')}
|
{t('common.openInNewTab')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
{!disabledFeatures.includes('lightbox') && (
|
{isLightboxEnabled && (
|
||||||
<MenuItem icon={<FaExpand />} onClickCapture={handleLightBox}>
|
<MenuItem icon={<FaExpand />} onClickCapture={handleLightBox}>
|
||||||
{t('parameters.openInViewer')}
|
{t('parameters.openInViewer')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<IoArrowUndoCircleOutline />}
|
icon={<IoArrowUndoCircleOutline />}
|
||||||
onClickCapture={handleUsePrompt}
|
onClickCapture={handleRecallPrompt}
|
||||||
isDisabled={image?.metadata?.invokeai?.node?.prompt === undefined}
|
isDisabled={image?.metadata?.invokeai?.node?.prompt === undefined}
|
||||||
>
|
>
|
||||||
{t('parameters.usePrompt')}
|
{t('parameters.usePrompt')}
|
||||||
@ -276,14 +221,14 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
|||||||
|
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<IoArrowUndoCircleOutline />}
|
icon={<IoArrowUndoCircleOutline />}
|
||||||
onClickCapture={handleUseSeed}
|
onClickCapture={handleRecallSeed}
|
||||||
isDisabled={image?.metadata?.invokeai?.node?.seed === undefined}
|
isDisabled={image?.metadata?.invokeai?.node?.seed === undefined}
|
||||||
>
|
>
|
||||||
{t('parameters.useSeed')}
|
{t('parameters.useSeed')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
icon={<IoArrowUndoCircleOutline />}
|
icon={<IoArrowUndoCircleOutline />}
|
||||||
onClickCapture={handleUseInitialImage}
|
onClickCapture={handleRecallInitialImage}
|
||||||
isDisabled={image?.metadata?.invokeai?.node?.type !== 'img2img'}
|
isDisabled={image?.metadata?.invokeai?.node?.type !== 'img2img'}
|
||||||
>
|
>
|
||||||
{t('parameters.useInitImg')}
|
{t('parameters.useInitImg')}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ButtonGroup, Flex, Grid, Icon, Image, Text } from '@chakra-ui/react';
|
import { ButtonGroup, Flex, Grid, Icon, Image, Text } from '@chakra-ui/react';
|
||||||
import { requestImages } from 'app/socketio/actions';
|
// import { requestImages } from 'app/socketio/actions';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import IAICheckbox from 'common/components/IAICheckbox';
|
import IAICheckbox from 'common/components/IAICheckbox';
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Box } from '@chakra-ui/react';
|
import { Box } from '@chakra-ui/react';
|
||||||
import { readinessSelector } from 'app/selectors/readinessSelector';
|
import { readinessSelector } from 'app/selectors/readinessSelector';
|
||||||
import { generateImage } from 'app/socketio/actions';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton, { IAIButtonProps } from 'common/components/IAIButton';
|
import IAIButton, { IAIButtonProps } from 'common/components/IAIButton';
|
||||||
import IAIIconButton, {
|
import IAIIconButton, {
|
||||||
@ -8,10 +7,11 @@ import IAIIconButton, {
|
|||||||
} from 'common/components/IAIIconButton';
|
} from 'common/components/IAIIconButton';
|
||||||
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
|
import { clampSymmetrySteps } from 'features/parameters/store/generationSlice';
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { FaPlay } from 'react-icons/fa';
|
import { FaPlay } from 'react-icons/fa';
|
||||||
import { generateGraphBuilt, sessionCreated } from 'services/thunks/session';
|
import { generateGraphBuilt } from 'services/thunks/session';
|
||||||
|
|
||||||
interface InvokeButton
|
interface InvokeButton
|
||||||
extends Omit<IAIButtonProps | IAIIconButtonProps, 'aria-label'> {
|
extends Omit<IAIButtonProps | IAIIconButtonProps, 'aria-label'> {
|
||||||
@ -24,19 +24,16 @@ export default function InvokeButton(props: InvokeButton) {
|
|||||||
const { isReady } = useAppSelector(readinessSelector);
|
const { isReady } = useAppSelector(readinessSelector);
|
||||||
const activeTabName = useAppSelector(activeTabNameSelector);
|
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||||
|
|
||||||
const handleClickGenerate = () => {
|
const handleInvoke = useCallback(() => {
|
||||||
// dispatch(generateImage(activeTabName));
|
dispatch(clampSymmetrySteps());
|
||||||
dispatch(generateGraphBuilt());
|
dispatch(generateGraphBuilt());
|
||||||
};
|
}, [dispatch]);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
['ctrl+enter', 'meta+enter'],
|
['ctrl+enter', 'meta+enter'],
|
||||||
() => {
|
handleInvoke,
|
||||||
dispatch(clampSymmetrySteps());
|
|
||||||
dispatch(generateImage(activeTabName));
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
enabled: () => isReady,
|
enabled: () => isReady,
|
||||||
preventDefault: true,
|
preventDefault: true,
|
||||||
@ -53,7 +50,7 @@ export default function InvokeButton(props: InvokeButton) {
|
|||||||
type="submit"
|
type="submit"
|
||||||
icon={<FaPlay />}
|
icon={<FaPlay />}
|
||||||
isDisabled={!isReady}
|
isDisabled={!isReady}
|
||||||
onClick={handleClickGenerate}
|
onClick={handleInvoke}
|
||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
w="100%"
|
w="100%"
|
||||||
tooltip={t('parameters.invoke')}
|
tooltip={t('parameters.invoke')}
|
||||||
@ -66,7 +63,7 @@ export default function InvokeButton(props: InvokeButton) {
|
|||||||
aria-label={t('parameters.invoke')}
|
aria-label={t('parameters.invoke')}
|
||||||
type="submit"
|
type="submit"
|
||||||
isDisabled={!isReady}
|
isDisabled={!isReady}
|
||||||
onClick={handleClickGenerate}
|
onClick={handleInvoke}
|
||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
w="100%"
|
w="100%"
|
||||||
colorScheme="accent"
|
colorScheme="accent"
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Box, FormControl, Textarea } from '@chakra-ui/react';
|
import { Box, FormControl, Textarea } from '@chakra-ui/react';
|
||||||
import { generateImage } from 'app/socketio/actions';
|
|
||||||
import { RootState } from 'app/store/store';
|
import { RootState } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { ChangeEvent, KeyboardEvent, useRef } from 'react';
|
import { ChangeEvent, KeyboardEvent, useRef } from 'react';
|
||||||
@ -8,6 +7,7 @@ import { createSelector } from '@reduxjs/toolkit';
|
|||||||
import { readinessSelector } from 'app/selectors/readinessSelector';
|
import { readinessSelector } from 'app/selectors/readinessSelector';
|
||||||
import {
|
import {
|
||||||
GenerationState,
|
GenerationState,
|
||||||
|
clampSymmetrySteps,
|
||||||
setPrompt,
|
setPrompt,
|
||||||
} from 'features/parameters/store/generationSlice';
|
} from 'features/parameters/store/generationSlice';
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
@ -15,6 +15,7 @@ import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
|||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { generateGraphBuilt } from 'services/thunks/session';
|
||||||
|
|
||||||
const promptInputSelector = createSelector(
|
const promptInputSelector = createSelector(
|
||||||
[(state: RootState) => state.generation, activeTabNameSelector],
|
[(state: RootState) => state.generation, activeTabNameSelector],
|
||||||
@ -36,7 +37,7 @@ const promptInputSelector = createSelector(
|
|||||||
*/
|
*/
|
||||||
const PromptInput = () => {
|
const PromptInput = () => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { prompt, activeTabName } = useAppSelector(promptInputSelector);
|
const { prompt } = useAppSelector(promptInputSelector);
|
||||||
const { isReady } = useAppSelector(readinessSelector);
|
const { isReady } = useAppSelector(readinessSelector);
|
||||||
|
|
||||||
const promptRef = useRef<HTMLTextAreaElement>(null);
|
const promptRef = useRef<HTMLTextAreaElement>(null);
|
||||||
@ -58,7 +59,8 @@ const PromptInput = () => {
|
|||||||
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
|
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
|
||||||
if (e.key === 'Enter' && e.shiftKey === false && isReady) {
|
if (e.key === 'Enter' && e.shiftKey === false && isReady) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
dispatch(generateImage(activeTabName));
|
dispatch(clampSymmetrySteps());
|
||||||
|
dispatch(generateGraphBuilt());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
import { useToast } from '@chakra-ui/react';
|
||||||
|
import { useAppDispatch } from 'app/store/storeHooks';
|
||||||
|
import { isFinite, isString } from 'lodash-es';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import useSetBothPrompts from './usePrompt';
|
||||||
|
import { initialImageSelected, setSeed } from '../store/generationSlice';
|
||||||
|
import { isImage, isImageField } from 'services/types/guards';
|
||||||
|
import { NUMPY_RAND_MAX } from 'app/constants';
|
||||||
|
|
||||||
|
export const useParameters = () => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const toast = useToast();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const setBothPrompts = useSetBothPrompts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets prompt with toast
|
||||||
|
*/
|
||||||
|
const recallPrompt = useCallback(
|
||||||
|
(prompt: unknown) => {
|
||||||
|
if (!isString(prompt)) {
|
||||||
|
toast({
|
||||||
|
title: t('toast.promptNotSet'),
|
||||||
|
description: t('toast.promptNotSetDesc'),
|
||||||
|
status: 'warning',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setBothPrompts(prompt);
|
||||||
|
toast({
|
||||||
|
title: t('toast.promptSet'),
|
||||||
|
status: 'info',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[t, toast, setBothPrompts]
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets seed with toast
|
||||||
|
*/
|
||||||
|
const recallSeed = useCallback(
|
||||||
|
(seed: unknown) => {
|
||||||
|
const s = Number(seed);
|
||||||
|
if (!isFinite(s) || (isFinite(s) && !(s >= 0 && s <= NUMPY_RAND_MAX))) {
|
||||||
|
toast({
|
||||||
|
title: t('toast.seedNotSet'),
|
||||||
|
description: t('toast.seedNotSetDesc'),
|
||||||
|
status: 'error',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(setSeed(s));
|
||||||
|
toast({
|
||||||
|
title: t('toast.seedSet'),
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[t, toast, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets initial image with toast
|
||||||
|
*/
|
||||||
|
const recallInitialImage = useCallback(
|
||||||
|
async (image: unknown) => {
|
||||||
|
if (!isImageField(image)) {
|
||||||
|
toast({
|
||||||
|
title: t('toast.initialImageNotSet'),
|
||||||
|
description: t('toast.initialImageNotSetDesc'),
|
||||||
|
status: 'error',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
initialImageSelected({ name: image.image_name, type: image.image_type })
|
||||||
|
);
|
||||||
|
toast({
|
||||||
|
title: t('toast.initialImageSet'),
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[t, toast, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets image as initial image with toast
|
||||||
|
*/
|
||||||
|
const sendToImageToImage = useCallback(
|
||||||
|
(image: unknown) => {
|
||||||
|
if (!isImage(image)) {
|
||||||
|
toast({
|
||||||
|
title: t('toast.imageNotLoaded'),
|
||||||
|
description: t('toast.imageNotLoadedDesc'),
|
||||||
|
status: 'error',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(initialImageSelected({ name: image.name, type: image.type }));
|
||||||
|
|
||||||
|
toast({
|
||||||
|
title: t('toast.sentToImageToImage'),
|
||||||
|
status: 'success',
|
||||||
|
duration: 2500,
|
||||||
|
isClosable: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[t, toast, dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { recallPrompt, recallSeed, recallInitialImage, sendToImageToImage };
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import { emptyTempFolder } from 'app/socketio/actions';
|
// import { emptyTempFolder } from 'app/socketio/actions';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
|
@ -17,7 +17,7 @@ import React from 'react';
|
|||||||
|
|
||||||
import SearchModels from './SearchModels';
|
import SearchModels from './SearchModels';
|
||||||
|
|
||||||
import { addNewModel } from 'app/socketio/actions';
|
// import { addNewModel } from 'app/socketio/actions';
|
||||||
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
VStack,
|
VStack,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { InvokeDiffusersModelConfigProps } from 'app/types/invokeai';
|
import { InvokeDiffusersModelConfigProps } from 'app/types/invokeai';
|
||||||
import { addNewModel } from 'app/socketio/actions';
|
// import { addNewModel } from 'app/socketio/actions';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import IAIInput from 'common/components/IAIInput';
|
import IAIInput from 'common/components/IAIInput';
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
VStack,
|
VStack,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
|
|
||||||
import { addNewModel } from 'app/socketio/actions';
|
// import { addNewModel } from 'app/socketio/actions';
|
||||||
import { Field, Formik } from 'formik';
|
import { Field, Formik } from 'formik';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import { systemSelector } from 'features/system/store/systemSelectors';
|
|||||||
|
|
||||||
import { Flex, FormControl, FormLabel, Text, VStack } from '@chakra-ui/react';
|
import { Flex, FormControl, FormLabel, Text, VStack } from '@chakra-ui/react';
|
||||||
|
|
||||||
import { addNewModel } from 'app/socketio/actions';
|
// import { addNewModel } from 'app/socketio/actions';
|
||||||
import { Field, Formik } from 'formik';
|
import { Field, Formik } from 'formik';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { mergeDiffusersModels } from 'app/socketio/actions';
|
// import { mergeDiffusersModels } from 'app/socketio/actions';
|
||||||
import { RootState } from 'app/store/store';
|
import { RootState } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
UnorderedList,
|
UnorderedList,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { convertToDiffusers } from 'app/socketio/actions';
|
// import { convertToDiffusers } from 'app/socketio/actions';
|
||||||
import { RootState } from 'app/store/store';
|
import { RootState } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { DeleteIcon, EditIcon } from '@chakra-ui/icons';
|
import { DeleteIcon, EditIcon } from '@chakra-ui/icons';
|
||||||
import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react';
|
import { Box, Button, Flex, Spacer, Text, Tooltip } from '@chakra-ui/react';
|
||||||
import { ModelStatus } from 'app/types/invokeai';
|
import { ModelStatus } from 'app/types/invokeai';
|
||||||
import { deleteModel, requestModelChange } from 'app/socketio/actions';
|
// import { deleteModel, requestModelChange } from 'app/socketio/actions';
|
||||||
import { RootState } from 'app/store/store';
|
import { RootState } from 'app/store/store';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
import IAIAlertDialog from 'common/components/IAIAlertDialog';
|
||||||
|
@ -20,7 +20,7 @@ import { useTranslation } from 'react-i18next';
|
|||||||
|
|
||||||
import { FaSearch, FaTrash } from 'react-icons/fa';
|
import { FaSearch, FaTrash } from 'react-icons/fa';
|
||||||
|
|
||||||
import { addNewModel, searchForModels } from 'app/socketio/actions';
|
// import { addNewModel, searchForModels } from 'app/socketio/actions';
|
||||||
import {
|
import {
|
||||||
setFoundModels,
|
setFoundModels,
|
||||||
setSearchFolder,
|
setSearchFolder,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ChakraProps,
|
ChakraProps,
|
||||||
Flex,
|
Flex,
|
||||||
Grid,
|
|
||||||
Heading,
|
Heading,
|
||||||
Modal,
|
Modal,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
@ -14,22 +13,16 @@ import {
|
|||||||
useDisclosure,
|
useDisclosure,
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { IN_PROGRESS_IMAGE_TYPES } from 'app/constants';
|
|
||||||
import { RootState } from 'app/store/store';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import IAIButton from 'common/components/IAIButton';
|
import IAIButton from 'common/components/IAIButton';
|
||||||
import IAINumberInput from 'common/components/IAINumberInput';
|
|
||||||
import IAISelect from 'common/components/IAISelect';
|
import IAISelect from 'common/components/IAISelect';
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
import IAISwitch from 'common/components/IAISwitch';
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import {
|
import {
|
||||||
consoleLogLevelChanged,
|
consoleLogLevelChanged,
|
||||||
InProgressImageType,
|
|
||||||
setEnableImageDebugging,
|
setEnableImageDebugging,
|
||||||
setSaveIntermediatesInterval,
|
|
||||||
setShouldConfirmOnDelete,
|
setShouldConfirmOnDelete,
|
||||||
setShouldDisplayGuides,
|
setShouldDisplayGuides,
|
||||||
setShouldDisplayInProgressType,
|
|
||||||
shouldLogToConsoleChanged,
|
shouldLogToConsoleChanged,
|
||||||
SystemState,
|
SystemState,
|
||||||
} from 'features/system/store/systemSlice';
|
} from 'features/system/store/systemSlice';
|
||||||
@ -39,23 +32,19 @@ import {
|
|||||||
setShouldUseSliders,
|
setShouldUseSliders,
|
||||||
} from 'features/ui/store/uiSlice';
|
} from 'features/ui/store/uiSlice';
|
||||||
import { UIState } from 'features/ui/store/uiTypes';
|
import { UIState } from 'features/ui/store/uiTypes';
|
||||||
import { isEqual, map } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { persistor } from 'app/store/persistor';
|
import { persistor } from 'app/store/persistor';
|
||||||
import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react';
|
import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger';
|
import { VALID_LOG_LEVELS } from 'app/logging/useLogger';
|
||||||
import { LogLevelName } from 'roarr';
|
import { LogLevelName } from 'roarr';
|
||||||
import { F } from 'ts-toolbelt';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[systemSelector, uiSelector],
|
[systemSelector, uiSelector],
|
||||||
(system: SystemState, ui: UIState) => {
|
(system: SystemState, ui: UIState) => {
|
||||||
const {
|
const {
|
||||||
shouldDisplayInProgressType,
|
|
||||||
shouldConfirmOnDelete,
|
shouldConfirmOnDelete,
|
||||||
shouldDisplayGuides,
|
shouldDisplayGuides,
|
||||||
model_list,
|
|
||||||
saveIntermediatesInterval,
|
|
||||||
enableImageDebugging,
|
enableImageDebugging,
|
||||||
consoleLogLevel,
|
consoleLogLevel,
|
||||||
shouldLogToConsole,
|
shouldLogToConsole,
|
||||||
@ -64,11 +53,8 @@ const selector = createSelector(
|
|||||||
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
|
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
shouldDisplayInProgressType,
|
|
||||||
shouldConfirmOnDelete,
|
shouldConfirmOnDelete,
|
||||||
shouldDisplayGuides,
|
shouldDisplayGuides,
|
||||||
models: map(model_list, (_model, key) => key),
|
|
||||||
saveIntermediatesInterval,
|
|
||||||
enableImageDebugging,
|
enableImageDebugging,
|
||||||
shouldUseCanvasBetaLayout,
|
shouldUseCanvasBetaLayout,
|
||||||
shouldUseSliders,
|
shouldUseSliders,
|
||||||
@ -104,8 +90,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const steps = useAppSelector((state: RootState) => state.generation.steps);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isOpen: isSettingsModalOpen,
|
isOpen: isSettingsModalOpen,
|
||||||
onOpen: onSettingsModalOpen,
|
onOpen: onSettingsModalOpen,
|
||||||
@ -119,10 +103,8 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
} = useDisclosure();
|
} = useDisclosure();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
shouldDisplayInProgressType,
|
|
||||||
shouldConfirmOnDelete,
|
shouldConfirmOnDelete,
|
||||||
shouldDisplayGuides,
|
shouldDisplayGuides,
|
||||||
saveIntermediatesInterval,
|
|
||||||
enableImageDebugging,
|
enableImageDebugging,
|
||||||
shouldUseCanvasBetaLayout,
|
shouldUseCanvasBetaLayout,
|
||||||
shouldUseSliders,
|
shouldUseSliders,
|
||||||
@ -134,18 +116,12 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
* Resets localstorage, then opens a secondary modal informing user to
|
* Resets localstorage, then opens a secondary modal informing user to
|
||||||
* refresh their browser.
|
* refresh their browser.
|
||||||
* */
|
* */
|
||||||
const handleClickResetWebUI = () => {
|
const handleClickResetWebUI = useCallback(() => {
|
||||||
persistor.purge().then(() => {
|
persistor.purge().then(() => {
|
||||||
onSettingsModalClose();
|
onSettingsModalClose();
|
||||||
onRefreshModalOpen();
|
onRefreshModalOpen();
|
||||||
});
|
});
|
||||||
};
|
}, [onSettingsModalClose, onRefreshModalOpen]);
|
||||||
|
|
||||||
const handleChangeIntermediateSteps = (value: number) => {
|
|
||||||
if (value > steps) value = steps;
|
|
||||||
if (value < 1) value = 1;
|
|
||||||
dispatch(setSaveIntermediatesInterval(value));
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleLogLevelChanged = useCallback(
|
const handleLogLevelChanged = useCallback(
|
||||||
(e: ChangeEvent<HTMLSelectElement>) => {
|
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
@ -182,32 +158,6 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
<Flex sx={modalSectionStyles}>
|
<Flex sx={modalSectionStyles}>
|
||||||
<Heading size="sm">{t('settings.general')}</Heading>
|
<Heading size="sm">{t('settings.general')}</Heading>
|
||||||
|
|
||||||
<IAISelect
|
|
||||||
horizontal
|
|
||||||
spaceEvenly
|
|
||||||
label={t('settings.displayInProgress')}
|
|
||||||
validValues={IN_PROGRESS_IMAGE_TYPES}
|
|
||||||
value={shouldDisplayInProgressType}
|
|
||||||
onChange={(e: ChangeEvent<HTMLSelectElement>) =>
|
|
||||||
dispatch(
|
|
||||||
setShouldDisplayInProgressType(
|
|
||||||
e.target.value as InProgressImageType
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{shouldDisplayInProgressType === 'full-res' && (
|
|
||||||
<IAINumberInput
|
|
||||||
label={t('settings.saveSteps')}
|
|
||||||
min={1}
|
|
||||||
max={steps}
|
|
||||||
step={1}
|
|
||||||
onChange={handleChangeIntermediateSteps}
|
|
||||||
value={saveIntermediatesInterval}
|
|
||||||
width="auto"
|
|
||||||
textAlign="center"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<IAISwitch
|
<IAISwitch
|
||||||
label={t('settings.confirmOnDelete')}
|
label={t('settings.confirmOnDelete')}
|
||||||
isChecked={shouldConfirmOnDelete}
|
isChecked={shouldConfirmOnDelete}
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
import { Text, Tooltip } from '@chakra-ui/react';
|
import { Text } from '@chakra-ui/react';
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { errorSeen, SystemState } from 'features/system/store/systemSlice';
|
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { systemSelector } from '../store/systemSelectors';
|
import { systemSelector } from '../store/systemSelectors';
|
||||||
|
|
||||||
const statusIndicatorSelector = createSelector(
|
const statusIndicatorSelector = createSelector(
|
||||||
systemSelector,
|
systemSelector,
|
||||||
(system: SystemState) => {
|
(system) => {
|
||||||
return {
|
return {
|
||||||
isConnected: system.isConnected,
|
isConnected: system.isConnected,
|
||||||
isProcessing: system.isProcessing,
|
isProcessing: system.isProcessing,
|
||||||
currentIteration: system.currentIteration,
|
currentIteration: system.currentIteration,
|
||||||
totalIterations: system.totalIterations,
|
totalIterations: system.totalIterations,
|
||||||
currentStatus: system.currentStatus,
|
currentStatus: system.currentStatus,
|
||||||
hasError: system.hasError,
|
|
||||||
wasErrorSeen: system.wasErrorSeen,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -31,15 +28,12 @@ const StatusIndicator = () => {
|
|||||||
currentIteration,
|
currentIteration,
|
||||||
totalIterations,
|
totalIterations,
|
||||||
currentStatus,
|
currentStatus,
|
||||||
hasError,
|
|
||||||
wasErrorSeen,
|
|
||||||
} = useAppSelector(statusIndicatorSelector);
|
} = useAppSelector(statusIndicatorSelector);
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
let statusIdentifier;
|
let statusIdentifier;
|
||||||
|
|
||||||
if (isConnected && !hasError) {
|
if (isConnected) {
|
||||||
statusIdentifier = 'ok';
|
statusIdentifier = 'ok';
|
||||||
} else {
|
} else {
|
||||||
statusIdentifier = 'error';
|
statusIdentifier = 'error';
|
||||||
@ -60,25 +54,8 @@ const StatusIndicator = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const tooltipLabel =
|
|
||||||
hasError && !wasErrorSeen
|
|
||||||
? 'Click to clear, check logs for details'
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const statusIndicatorCursor =
|
|
||||||
hasError && !wasErrorSeen ? 'pointer' : 'initial';
|
|
||||||
|
|
||||||
const handleClickStatusIndicator = () => {
|
|
||||||
if (hasError || !wasErrorSeen) {
|
|
||||||
dispatch(errorSeen());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip label={tooltipLabel}>
|
|
||||||
<Text
|
<Text
|
||||||
cursor={statusIndicatorCursor}
|
|
||||||
onClick={handleClickStatusIndicator}
|
|
||||||
sx={{
|
sx={{
|
||||||
fontSize: 'sm',
|
fontSize: 'sm',
|
||||||
fontWeight: '600',
|
fontWeight: '600',
|
||||||
@ -87,7 +64,6 @@ const StatusIndicator = () => {
|
|||||||
>
|
>
|
||||||
{t(statusMessage as keyof typeof t)}
|
{t(statusMessage as keyof typeof t)}
|
||||||
</Text>
|
</Text>
|
||||||
</Tooltip>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -23,33 +23,14 @@ import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
|||||||
import { LogLevelName } from 'roarr';
|
import { LogLevelName } from 'roarr';
|
||||||
import { InvokeLogLevel } from 'app/logging/useLogger';
|
import { InvokeLogLevel } from 'app/logging/useLogger';
|
||||||
|
|
||||||
export type LogLevel = 'info' | 'warning' | 'error';
|
|
||||||
|
|
||||||
export interface LogEntry {
|
|
||||||
timestamp: string;
|
|
||||||
level: LogLevel;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Log {
|
|
||||||
[index: number]: LogEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type InProgressImageType = 'none' | 'full-res' | 'latents';
|
|
||||||
|
|
||||||
export type CancelType = 'immediate' | 'scheduled';
|
export type CancelType = 'immediate' | 'scheduled';
|
||||||
|
|
||||||
export interface SystemState
|
export interface SystemState {
|
||||||
extends InvokeAI.SystemStatus,
|
|
||||||
InvokeAI.SystemConfig {
|
|
||||||
shouldDisplayInProgressType: InProgressImageType;
|
|
||||||
shouldShowLogViewer: boolean;
|
|
||||||
isGFPGANAvailable: boolean;
|
isGFPGANAvailable: boolean;
|
||||||
isESRGANAvailable: boolean;
|
isESRGANAvailable: boolean;
|
||||||
isConnected: boolean;
|
isConnected: boolean;
|
||||||
socketId: string;
|
isProcessing: boolean;
|
||||||
shouldConfirmOnDelete: boolean;
|
shouldConfirmOnDelete: boolean;
|
||||||
openAccordions: ExpandedIndex;
|
|
||||||
currentStep: number;
|
currentStep: number;
|
||||||
totalSteps: number;
|
totalSteps: number;
|
||||||
currentIteration: number;
|
currentIteration: number;
|
||||||
@ -57,18 +38,12 @@ export interface SystemState
|
|||||||
currentStatus: string;
|
currentStatus: string;
|
||||||
currentStatusHasSteps: boolean;
|
currentStatusHasSteps: boolean;
|
||||||
shouldDisplayGuides: boolean;
|
shouldDisplayGuides: boolean;
|
||||||
wasErrorSeen: boolean;
|
|
||||||
isCancelable: boolean;
|
isCancelable: boolean;
|
||||||
saveIntermediatesInterval: number;
|
|
||||||
enableImageDebugging: boolean;
|
enableImageDebugging: boolean;
|
||||||
toastQueue: UseToastOptions[];
|
toastQueue: UseToastOptions[];
|
||||||
searchFolder: string | null;
|
searchFolder: string | null;
|
||||||
foundModels: InvokeAI.FoundModel[] | null;
|
foundModels: InvokeAI.FoundModel[] | null;
|
||||||
openModel: string | null;
|
openModel: string | null;
|
||||||
cancelOptions: {
|
|
||||||
cancelType: CancelType;
|
|
||||||
cancelAfter: number | null;
|
|
||||||
};
|
|
||||||
/**
|
/**
|
||||||
* The current progress image
|
* The current progress image
|
||||||
*/
|
*/
|
||||||
@ -107,14 +82,10 @@ export interface SystemState
|
|||||||
const initialSystemState: SystemState = {
|
const initialSystemState: SystemState = {
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
isProcessing: false,
|
isProcessing: false,
|
||||||
shouldShowLogViewer: false,
|
|
||||||
shouldDisplayInProgressType: 'latents',
|
|
||||||
shouldDisplayGuides: true,
|
shouldDisplayGuides: true,
|
||||||
isGFPGANAvailable: true,
|
isGFPGANAvailable: true,
|
||||||
isESRGANAvailable: true,
|
isESRGANAvailable: true,
|
||||||
socketId: '',
|
|
||||||
shouldConfirmOnDelete: true,
|
shouldConfirmOnDelete: true,
|
||||||
openAccordions: [0],
|
|
||||||
currentStep: 0,
|
currentStep: 0,
|
||||||
totalSteps: 0,
|
totalSteps: 0,
|
||||||
currentIteration: 0,
|
currentIteration: 0,
|
||||||
@ -123,26 +94,12 @@ const initialSystemState: SystemState = {
|
|||||||
? i18n.t('common.statusDisconnected')
|
? i18n.t('common.statusDisconnected')
|
||||||
: 'Disconnected',
|
: 'Disconnected',
|
||||||
currentStatusHasSteps: false,
|
currentStatusHasSteps: false,
|
||||||
model: '',
|
|
||||||
model_id: '',
|
|
||||||
model_hash: '',
|
|
||||||
app_id: '',
|
|
||||||
app_version: '',
|
|
||||||
model_list: {},
|
|
||||||
infill_methods: [],
|
|
||||||
hasError: false,
|
|
||||||
wasErrorSeen: true,
|
|
||||||
isCancelable: true,
|
isCancelable: true,
|
||||||
saveIntermediatesInterval: 5,
|
|
||||||
enableImageDebugging: false,
|
enableImageDebugging: false,
|
||||||
toastQueue: [],
|
toastQueue: [],
|
||||||
searchFolder: null,
|
searchFolder: null,
|
||||||
foundModels: null,
|
foundModels: null,
|
||||||
openModel: null,
|
openModel: null,
|
||||||
cancelOptions: {
|
|
||||||
cancelType: 'immediate',
|
|
||||||
cancelAfter: null,
|
|
||||||
},
|
|
||||||
progressImage: null,
|
progressImage: null,
|
||||||
sessionId: null,
|
sessionId: null,
|
||||||
cancelType: 'immediate',
|
cancelType: 'immediate',
|
||||||
@ -158,23 +115,13 @@ export const systemSlice = createSlice({
|
|||||||
name: 'system',
|
name: 'system',
|
||||||
initialState: initialSystemState,
|
initialState: initialSystemState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setShouldDisplayInProgressType: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<InProgressImageType>
|
|
||||||
) => {
|
|
||||||
state.shouldDisplayInProgressType = action.payload;
|
|
||||||
},
|
|
||||||
setIsProcessing: (state, action: PayloadAction<boolean>) => {
|
setIsProcessing: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isProcessing = action.payload;
|
state.isProcessing = action.payload;
|
||||||
},
|
},
|
||||||
setCurrentStatus: (state, action: PayloadAction<string>) => {
|
setCurrentStatus: (state, action: PayloadAction<string>) => {
|
||||||
state.currentStatus = action.payload;
|
state.currentStatus = action.payload;
|
||||||
},
|
},
|
||||||
setSystemStatus: (state, action: PayloadAction<InvokeAI.SystemStatus>) => {
|
|
||||||
return { ...state, ...action.payload };
|
|
||||||
},
|
|
||||||
errorOccurred: (state) => {
|
errorOccurred: (state) => {
|
||||||
state.hasError = true;
|
|
||||||
state.isProcessing = false;
|
state.isProcessing = false;
|
||||||
state.isCancelable = true;
|
state.isCancelable = true;
|
||||||
state.currentStep = 0;
|
state.currentStep = 0;
|
||||||
@ -183,17 +130,6 @@ export const systemSlice = createSlice({
|
|||||||
state.totalIterations = 0;
|
state.totalIterations = 0;
|
||||||
state.currentStatusHasSteps = false;
|
state.currentStatusHasSteps = false;
|
||||||
state.currentStatus = i18n.t('common.statusError');
|
state.currentStatus = i18n.t('common.statusError');
|
||||||
state.wasErrorSeen = false;
|
|
||||||
},
|
|
||||||
errorSeen: (state) => {
|
|
||||||
state.hasError = false;
|
|
||||||
state.wasErrorSeen = true;
|
|
||||||
state.currentStatus = state.isConnected
|
|
||||||
? i18n.t('common.statusConnected')
|
|
||||||
: i18n.t('common.statusDisconnected');
|
|
||||||
},
|
|
||||||
setShouldShowLogViewer: (state, action: PayloadAction<boolean>) => {
|
|
||||||
state.shouldShowLogViewer = action.payload;
|
|
||||||
},
|
},
|
||||||
setIsConnected: (state, action: PayloadAction<boolean>) => {
|
setIsConnected: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isConnected = action.payload;
|
state.isConnected = action.payload;
|
||||||
@ -204,23 +140,10 @@ export const systemSlice = createSlice({
|
|||||||
state.currentIteration = 0;
|
state.currentIteration = 0;
|
||||||
state.totalIterations = 0;
|
state.totalIterations = 0;
|
||||||
state.currentStatusHasSteps = false;
|
state.currentStatusHasSteps = false;
|
||||||
state.hasError = false;
|
|
||||||
},
|
|
||||||
setSocketId: (state, action: PayloadAction<string>) => {
|
|
||||||
state.socketId = action.payload;
|
|
||||||
},
|
},
|
||||||
setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => {
|
setShouldConfirmOnDelete: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldConfirmOnDelete = action.payload;
|
state.shouldConfirmOnDelete = action.payload;
|
||||||
},
|
},
|
||||||
setOpenAccordions: (state, action: PayloadAction<ExpandedIndex>) => {
|
|
||||||
state.openAccordions = action.payload;
|
|
||||||
},
|
|
||||||
setSystemConfig: (state, action: PayloadAction<InvokeAI.SystemConfig>) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
...action.payload,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
setShouldDisplayGuides: (state, action: PayloadAction<boolean>) => {
|
setShouldDisplayGuides: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldDisplayGuides = action.payload;
|
state.shouldDisplayGuides = action.payload;
|
||||||
},
|
},
|
||||||
@ -244,12 +167,6 @@ export const systemSlice = createSlice({
|
|||||||
state.currentStatusHasSteps = false;
|
state.currentStatusHasSteps = false;
|
||||||
state.currentStatus = i18n.t('common.statusPreparing');
|
state.currentStatus = i18n.t('common.statusPreparing');
|
||||||
},
|
},
|
||||||
setModelList: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<InvokeAI.ModelList | Record<string, never>>
|
|
||||||
) => {
|
|
||||||
state.model_list = action.payload;
|
|
||||||
},
|
|
||||||
setIsCancelable: (state, action: PayloadAction<boolean>) => {
|
setIsCancelable: (state, action: PayloadAction<boolean>) => {
|
||||||
state.isCancelable = action.payload;
|
state.isCancelable = action.payload;
|
||||||
},
|
},
|
||||||
@ -271,9 +188,6 @@ export const systemSlice = createSlice({
|
|||||||
state.isProcessing = true;
|
state.isProcessing = true;
|
||||||
state.currentStatusHasSteps = false;
|
state.currentStatusHasSteps = false;
|
||||||
},
|
},
|
||||||
setSaveIntermediatesInterval: (state, action: PayloadAction<number>) => {
|
|
||||||
state.saveIntermediatesInterval = action.payload;
|
|
||||||
},
|
|
||||||
setEnableImageDebugging: (state, action: PayloadAction<boolean>) => {
|
setEnableImageDebugging: (state, action: PayloadAction<boolean>) => {
|
||||||
state.enableImageDebugging = action.payload;
|
state.enableImageDebugging = action.payload;
|
||||||
},
|
},
|
||||||
@ -300,12 +214,6 @@ export const systemSlice = createSlice({
|
|||||||
setOpenModel: (state, action: PayloadAction<string | null>) => {
|
setOpenModel: (state, action: PayloadAction<string | null>) => {
|
||||||
state.openModel = action.payload;
|
state.openModel = action.payload;
|
||||||
},
|
},
|
||||||
setCancelType: (state, action: PayloadAction<CancelType>) => {
|
|
||||||
state.cancelOptions.cancelType = action.payload;
|
|
||||||
},
|
|
||||||
setCancelAfter: (state, action: PayloadAction<number | null>) => {
|
|
||||||
state.cancelOptions.cancelAfter = action.payload;
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* A cancel was scheduled
|
* A cancel was scheduled
|
||||||
*/
|
*/
|
||||||
@ -420,7 +328,6 @@ export const systemSlice = createSlice({
|
|||||||
builder.addCase(invocationError, (state, action) => {
|
builder.addCase(invocationError, (state, action) => {
|
||||||
const { data, timestamp } = action.payload;
|
const { data, timestamp } = action.payload;
|
||||||
|
|
||||||
state.wasErrorSeen = true;
|
|
||||||
state.progressImage = null;
|
state.progressImage = null;
|
||||||
state.isProcessing = false;
|
state.isProcessing = false;
|
||||||
|
|
||||||
@ -479,26 +386,17 @@ export const systemSlice = createSlice({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
setShouldDisplayInProgressType,
|
|
||||||
setIsProcessing,
|
setIsProcessing,
|
||||||
setShouldShowLogViewer,
|
|
||||||
setIsConnected,
|
setIsConnected,
|
||||||
setSocketId,
|
|
||||||
setShouldConfirmOnDelete,
|
setShouldConfirmOnDelete,
|
||||||
setOpenAccordions,
|
|
||||||
setSystemStatus,
|
|
||||||
setCurrentStatus,
|
setCurrentStatus,
|
||||||
setSystemConfig,
|
|
||||||
setShouldDisplayGuides,
|
setShouldDisplayGuides,
|
||||||
processingCanceled,
|
processingCanceled,
|
||||||
errorOccurred,
|
errorOccurred,
|
||||||
errorSeen,
|
|
||||||
setModelList,
|
|
||||||
setIsCancelable,
|
setIsCancelable,
|
||||||
modelChangeRequested,
|
modelChangeRequested,
|
||||||
modelConvertRequested,
|
modelConvertRequested,
|
||||||
modelMergingRequested,
|
modelMergingRequested,
|
||||||
setSaveIntermediatesInterval,
|
|
||||||
setEnableImageDebugging,
|
setEnableImageDebugging,
|
||||||
generationRequested,
|
generationRequested,
|
||||||
addToast,
|
addToast,
|
||||||
@ -507,8 +405,6 @@ export const {
|
|||||||
setSearchFolder,
|
setSearchFolder,
|
||||||
setFoundModels,
|
setFoundModels,
|
||||||
setOpenModel,
|
setOpenModel,
|
||||||
setCancelType,
|
|
||||||
setCancelAfter,
|
|
||||||
cancelScheduled,
|
cancelScheduled,
|
||||||
scheduledCancelAborted,
|
scheduledCancelAborted,
|
||||||
cancelTypeChanged,
|
cancelTypeChanged,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { Image } from 'app/types/invokeai';
|
||||||
|
import { get, isObject, isString } from 'lodash-es';
|
||||||
import {
|
import {
|
||||||
GraphExecutionState,
|
GraphExecutionState,
|
||||||
GraphInvocationOutput,
|
GraphInvocationOutput,
|
||||||
@ -6,6 +8,8 @@ import {
|
|||||||
PromptOutput,
|
PromptOutput,
|
||||||
IterateInvocationOutput,
|
IterateInvocationOutput,
|
||||||
CollectInvocationOutput,
|
CollectInvocationOutput,
|
||||||
|
ImageType,
|
||||||
|
ImageField,
|
||||||
} from 'services/api';
|
} from 'services/api';
|
||||||
|
|
||||||
export const isImageOutput = (
|
export const isImageOutput = (
|
||||||
@ -31,3 +35,16 @@ export const isIterateOutput = (
|
|||||||
export const isCollectOutput = (
|
export const isCollectOutput = (
|
||||||
output: GraphExecutionState['results'][string]
|
output: GraphExecutionState['results'][string]
|
||||||
): output is CollectInvocationOutput => output.type === 'collect_output';
|
): output is CollectInvocationOutput => output.type === 'collect_output';
|
||||||
|
|
||||||
|
export const isImageType = (t: unknown): t is ImageType =>
|
||||||
|
isString(t) && ['results', 'uploads', 'intermediates'].includes(t);
|
||||||
|
|
||||||
|
export const isImage = (image: unknown): image is Image =>
|
||||||
|
isObject(image) &&
|
||||||
|
isString(get(image, 'name')) &&
|
||||||
|
isImageType(get(image, 'type'));
|
||||||
|
|
||||||
|
export const isImageField = (imageField: unknown): imageField is ImageField =>
|
||||||
|
isObject(imageField) &&
|
||||||
|
isString(get(imageField, 'image_name')) &&
|
||||||
|
isImageType(get(imageField, 'image_type'));
|
||||||
|
Reference in New Issue
Block a user